2

So I have this code which works fine

#include <stdio.h>
#define B(X) &X
struct abc{
    char temp[2];
};

void print(char *string)
{
    printf("%s\n", string);
}
int main()
{
    struct abc *pAbc = malloc(sizeof(struct abc));
    pAbc->temp[0] = 'a';
    pAbc->temp[1] = '\0';
    print(pAbc->temp);
    free(pAbc);
    return 0;
}

but this does not work

#include <stdio.h>
#define B(X) &X
struct abc{
    char temp[2];
};

void print(char **string)
{
    printf("%s\n", *string);
}
int main()
{
    struct abc *pAbc = malloc(sizeof(struct abc));
    pAbc->temp[0] = 'a';
    pAbc->temp[1] = '\0';
    print(B(pAbc->temp));
    free(pAbc);
    return 0;
}

as I understand it the macro defination should return the address of the variable.

This function works fine with int.

EDIT:

Sorry I forgot to mention what I wanted to do, I want to pass a pointer to a pointer to the function, since I want to do it only for some compile paths I want to set an option like

if #defined WIN32
print(B(varible))
elif #defined GCC
print(varible)
gsamaras
  • 71,951
  • 46
  • 188
  • 305
qwn
  • 347
  • 3
  • 15
  • 1
    Possible duplicate of [How come an array's address is equal to its value in C?](https://stackoverflow.com/questions/2528318/how-come-an-arrays-address-is-equal-to-its-value-in-c) – Déjà vu Dec 01 '17 at 07:46
  • @RingØ I am not sure if this is dupe, why you say that? – gsamaras Dec 01 '17 at 07:47
  • It's a *possible* dupe because the basic reason of the issue is that `x` and `&x` return the same address. Reading that mentioned Q&A would avoid the mistake. Don't vote for it if you don't agree. – Déjà vu Dec 01 '17 at 07:53
  • 1
    `pAbc->temp` and `&pAbc->temp` are not the same thing, if it's done through a macro or not is irrelevant. – Art Dec 01 '17 at 08:52

4 Answers4

1

You can try

printf("%p %p",pAbc->temp,&pAbc->temp);

to see they both evaluate to same address, inside print you are wrongly expecting double pointer leading to invalid memory access

Pras
  • 4,047
  • 10
  • 20
1

Did you compile with warnings enabled? You should get:

prog.c:3:14: warning: passing argument 1 of 'print' from incompatible pointer type [-Wincompatible-pointer-types]
 #define B(X) &X
              ^~
prog.c:17:11: note: in expansion of macro 'B'
     print(B(pAbc->temp));
           ^
prog.c:8:19: note: expected 'char **' but argument is of type 'char (*)[2]'
 void print(char **string)
            ~~~~~~~^~~~~~

You don't need a double pointer in your print function, so just modify it back to using one pointer, and change this:

#define B(X) &X

to this:

#define B(X) X

EDIT:

What you want to do can easily be achieved without using a macro, like this:

char* temp= pAbc->temp;
print(&temp);
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 2
    What I want to do is pass a double pointer for some compile paths for which I want to create a macro. Edited the question. – qwn Dec 01 '17 at 07:43
1

The problem is that &pAbc->temp has type char (*)[2], not char **. In fact, you should have gotten a compilation error (or at least a warning) about incompatible pointer types (do you have warnings enabled?)

If you want to get a char **, you can do:

char *tmp = pAbc->temp;

then use &tmp as the argument to print.

But, why do you want the extra level of indirection? It's generally only needed if you want to modify the pointer from within the called function, which in this case isn't possible (it would basically mean changing the address of the array). The solution I gave will work, but you'd end up changing tmp in that case, which is of questionable usefulness.

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
1

You are sending a wrong argument to your function. That lead to an undefined behavior. The correct way, to sent an address of the address of an array in a structure is to use a temporary variable.

#include <stdio.h>

struct foo {
  char bar[2];
};

static void print(char **string) { printf("%s\n", *string); }

int main() {
  struct foo a = {.bar = "a"};
  char *p = a.bar;
  print(&p);
}
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • 1
    "You are sending a wrong argument to your function, it's undefined behavior." - Just to clarify, in general, is sending a `char` to a function expecting `int` UB? I guess not. – babon Dec 01 '17 at 08:17
  • @babon I do not want to say that. – Stargateur Dec 01 '17 at 08:27
  • :) Yes, I do understand that. Was just pointing out what that sentence might mean to someone in a general sense, that's all. – babon Dec 01 '17 at 08:40