-2

From my previous question double pointer vs pointer to array, incompatible pointer type, I use a fixed pointer (pointer to array) instead of modifiable pointer (double pointer), So I thinking if there is a way to cast and so change to compatible pointer type from one to another. (I won't post the source, since it could be seemed as duplicating, but my concern is in asm solution of that, so see the link first please).

As I saw a compiled assembly with -S flag, the string org is passed on stack (starting at address -64(%rbp)) and then passing that address to function strsep by leaq -64(%rbp), %rax. So everything looks good. here's asm snippet:

main:
    pushq   %rbp    #
    movq    %rsp, %rbp  #,
    subq    $64, %rsp   #,
# a.c:6:     char *token, org[] = "Cats,Dogs,Mice,,,Dwarves,Elves:High,Elves:Wood";
    movabsq $7453250866027716931, %rax  #, tmp93
    movabsq $3183030514286931059, %rdx  #,
    movq    %rax, -64(%rbp) # tmp93, org
    movq    %rdx, -56(%rbp) #, org
    movabsq $8315182520643044396, %rax  #, tmp94
    movabsq $5204599198995727660, %rdx  #,
    movq    %rax, -48(%rbp) # tmp94, org
    movq    %rdx, -40(%rbp) #, org
    movabsq $7311150089436161897, %rax  #, tmp95
    movq    %rax, -32(%rbp) # tmp95, org
    movl    $1867987571, -24(%rbp)  #, org
    movw    $25711, -20(%rbp)   #, org
    movb    $0, -18(%rbp)   #, org
# a.c:7:     while((token=strsep((char**)&org,",")))
    jmp .L2 #
.L3:
# a.c:8:         printf("Token: %s\n",token);
    movq    -8(%rbp), %rax  # token, tmp89
    movq    %rax, %rsi  # tmp89,
    leaq    .LC0(%rip), %rdi    #,
    movl    $0, %eax    #,
    call    printf@PLT  #
.L2:
# a.c:7:     while((token=strsep((char**)&org,",")))
    leaq    -64(%rbp), %rax #, tmp90
    leaq    .LC1(%rip), %rsi    #,
    movq    %rax, %rdi  # tmp90,
    call    strsep@PLT  #
    movq    %rax, -8(%rbp)  # tmp91, token
# a.c:7:     while((token=strsep((char**)&org,",")))
    ...

But in the end, it gets sigint. I know the strsep wants a type (char**), a address of pointer but I am giving it address of -64(%rbp) which should contain the same. So why the sigint? 2. How to properly cast incompatible pointer types to their compatible equivalents?

EDIT: This is not the same question. In the link, I asked about the intepretation in c. Now I ask about the solution in asm. It may look misleading, but I like to dissasembly c I do not understand. For those how thinks I am asking the same problem, I am not. Please for asnweres, look at the link first, I want assemblt solution here

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • do not ask same questions all over again. Do not abuse the system – 0___________ Jun 21 '20 at 20:52
  • @P__J__ editted. This is **not** duplicate. It is concernig the same issue, but in different view. – milanHrabos Jun 21 '20 at 20:57
  • 1
    Modify your original question. That is the correct way. We have explained that array is not the pointer. You can't cast it do double pointer. – 0___________ Jun 21 '20 at 20:59
  • 1
    @P__J__: The correct way would be to modify *this* question to ask about the asm in more detail, not to start with the same C question. `lea -64(%rbp)` isn't the *address* of a pointer, it just *is* a pointer to char data that was just stored. e.g. `(char*)7453250866027716931` is pointer value that `strsep` will try to use. The cast simply lies to the compiler about what it points to. That was all clearly explained in the C answer to the other question, but the OP is seeing what they expect to see, not what's actually there, when looking at the asm. – Peter Cordes Jun 21 '20 at 21:01
  • @PeterCordes So what can I modify (in asm, not in c) in order to not sigint? – milanHrabos Jun 21 '20 at 21:06
  • @PeterCordes he is not asking about the assembly. The assembly is to proof that we were all wrong in our answers. – 0___________ Jun 21 '20 at 21:06
  • This question already has a correct C answer! Compile it and compare the asm to see what correct asm looks like, obviously. Maybe that will help you understand what the difference in C really means. e.g. https://godbolt.org/z/XrdesD shows the good version vs. your bad version, with optimization to remove noise. Also, SIGINT is pretty unlikely; much more likely you're getting SIGSEGV from a bad pointer. – Peter Cordes Jun 21 '20 at 21:07

1 Answers1

1

Taking the address of a char [N] array results in a char (*)[N] array pointer. This is very different from a char **. The former does not create a new pointer variable, which is what you need.

Try the following:

int main(){
    char *token, org[] = "Cats,Dogs,Mice,,,Dwarves,Elves:High,Elves:Wood";
    char *ptr = org;
    while((token=strsep(&ptr,",")))
        printf("Token: %s\n",token);
}

This should do what you want. Note that ptr is modified by the call to strsep.

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
  • It might be even clearer to write `char org[] = "..."` as a separate statement, just to avoid any possible confusion about it being `char *org[]` (which would need a braced initializer list of strings). This feature of C grammar is usually best avoided for clarity. e.g. `char org[] = "...";` / `char *token, *ptr = org;` to group declarations of things with the same type together. – Peter Cordes Jun 21 '20 at 20:51
  • he asked this question 6 hours ago. He got the answers. – 0___________ Jun 21 '20 at 20:53
  • yes you right, that is a solution, but that was *already* solution to my linked question. Now I am asking about *casting* between those pointers, becuase as you can see from the assembly (which does care about types), the address refers to the same memory which `strsep` function wants (pointer to pointer). [Assembly does not care about type `(char*)[N]` or `char**`, it just see address - `-64(%rbp)` in this case` and takes it. And that is what I am asking for. So sorry, this is not answer to *this* (not linked) question – milanHrabos Jun 21 '20 at 20:54
  • @P__J__ see the comment. This is **not** the same question – milanHrabos Jun 21 '20 at 20:54
  • @milanHrabos you got the answer - you cant cast it. array will not become magically a double pointer. the answer covers your question. – 0___________ Jun 21 '20 at 20:55
  • @P__J__ see edits – milanHrabos Jun 21 '20 at 20:58
  • @milanHrabos edit the original question - do not ask new – 0___________ Jun 21 '20 at 21:00
  • @PeterCordes I agree about splitting the declarations being clearer, but that's how it was in the original code and it has no direct bearing on the problem, so I left it unchanged. – Tom Karzes Jun 21 '20 at 21:04
  • 1
    @milanHrabos Taking the address of an array in C is similar to a type cast. For instance, `(void *) org == (void *) &org` will be true if `org` is an array. The *type* changes, but the pointer value is the same. No code is generated for the type cast. There is no way to achieve what you need through a type cast, because you actually need a new pointer variable (and which can be modified) that points to the array. – Tom Karzes Jun 21 '20 at 21:11