0
int main(int argc, char *argv[])
{
  
  char b[]="Among Us";
  char* string2 = &b[0];
  
  printf("Print address of b\t\t=  %p\n", &b[0]);
  
  printf("Print content of string2\t=  %p\n", string2);
  printf("Print content of string2\t=  %s\n", string2); // why ???
  
  system("PAUSE");  
  return 0;
}

Why does the last printf show us the content of b? Isn't it supposed to show us the address of b but in %s format?

I thought printf("Print content of string2\t= %s\n", *string2); was the correct method of getting the content of b printed out through string2 but apparently it was the wrong way.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 1
    `%s` expects a pointer to char, internally it dereferences it. If you pass `*string2` it will interpret the char value as a pointer and you will most likely hit a segmentation fault – joH1 Mar 16 '22 at 10:08
  • `&b[0]` is the memory address of the first char of the `b` array. `b` is the memory address of the `b` array which by definition is the memory address of the first element of the `b` array. IOW `b` represents the same memory address than `&b[0]`. Or still IOW: `char* string2 = &b[0]` is the same thing as `char* string2 = b`. – Jabberwocky Mar 16 '22 at 10:16
  • @Jabberwocky I'm a bit confused here. [This website](https://www.geeksforgeeks.org/whats-difference-between-array-and-array-for-int-array5/) suggests **&array** is a pointer to whole array and **array** is a pointer to the first element of array. So I'm still not sure which one represents the whole array. My books do not specifically explain these things. – code_rookie Mar 16 '22 at 12:43
  • @code_rookie read that text closely in the link you mentioned: _.May be it’s too soon to conclude. The crux of this post is that even though they **both are resulting in same address** but they are different types of addresses._ – Jabberwocky Mar 16 '22 at 12:48
  • @Jabberwocky Thanks. I will find time to digest the whole array name and pointer thing. – code_rookie Mar 16 '22 at 13:13

4 Answers4

0

printf("Print content of string2\t= %s\n", string2);

Will print the entire string even when there is no deference operator before string2, because %s, as defined by the standard, expects a char *, i.e. an address. Refer here

Kartikeya
  • 818
  • 2
  • 6
  • 11
0

Why does the last printf show us the content of b?

address of first element in an array is an address of the array itself. => you can use string2 as b as well

Variable names don't exist anymore after the compiler runs , program care address of variable

refer this : How are variable names stored in memory in C?

long.kl
  • 670
  • 4
  • 12
0

You'd better revisit the memory addresses & pointers chapter of your C book.

Suppose you're running a 32 bits system, which addresses memory using 4 bytes & the memory state of your code is:

// char array "b"
address   value
=======   =====
aaaa:0001 A // hex value 41
aaaa:0002 m // hex value 6d
aaaa:0003 o // hex value 6f
aaaa:0004 n // hex value 6e
aaaa:0005 g
aaaa:0006   // that's a "space" char, hex value 20
aaaa:0007 U
aaaa:0008 s
aaaa:0009 0 // that's a zero, hex value 00

// pointer "string2"
// pointing to "aaaa:0001"
// in reverse order
// depending on endianness of your system
address   value
=======   =====
ffff:0001 01
ffff:0002 00
ffff:0003 aa
ffff:0004 aa
  1. Your first printf will print aaaa:0001 as hex; i.e. the memory address of array b.
  2. Your second printf will print aaaa:0001 as hex; i.e. the values stored in address ffff:0001 through ffff:0004. From the format specifier %p, the compiler will know that it's going to print a memory address and read the 4 bytes & revert them before printing.
  3. Your third printf will print Among Us; From the format specifier %s, the compiler will know that it's going to print a char array & print the chars at the address it was pointed to, until printf reaches to a string terminator which is a 0.
ssd
  • 2,340
  • 5
  • 19
  • 37
  • 1. The C standard does not specify the manner in which pointers are printed with `%p`; the output will not necessarily be “aaaa:0001”. – Eric Postpischil Mar 16 '22 at 10:35
  • 2. The C standard does not specify how pointers are represented or anything about reversing bytes of a memory address before printing. – Eric Postpischil Mar 16 '22 at 10:36
  • @thebusybee: The C standard does not specify anything about how pointers are formatted with `%p` except that the value is converted to “a sequence of printing characters.” Beyond that, the manner is entirely implementation-defined. – Eric Postpischil Mar 16 '22 at 10:37
  • Note there is no single definition for “32 bits system”, so it is best to avoid thinking of programming in such terms. Computer systems have many features which can vary in width, such as bus width, general processor register width, data widths in instructions, instruction size, address space, and more. Some processors have different widths for these different features. Further, the widths used in a C implementation are determined by the C implementation, not by the target hardware. – Eric Postpischil Mar 16 '22 at 10:39
  • @EricPostpischil : It was just to help visualize the *general* memory structure & which `printf` is printing which: The output of first & second `printf` are same but first one prints the memory address and it's *literally* printing the memory address. The second one prints a value (which is a memory address stored in a pointer type variable). – ssd Mar 16 '22 at 10:47
0

Both specifiers %p and %s expect a pointer.

%p will print the value of the pointer.

But %s will use the pointer to print a C string, that is an array of char delimited by '\0'.

If you give *string2, it is not a pointer. It is the value of the object the pointer points to, in your case a char.

Raise the warning level of your compiler to the maximum, and hope that it is smart enough to recognize format strings and to check the arguments.

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • Re “Raise the warning level of your compiler to the maximum, and hope that it is smart enough to recognize format strings and to check the arguments.”: What warning do you think a compiler would give here? `char* string2 = &b[0];` initializes a `char *` from a `char *`, so there is nothing to warn about there. Printing a pointer with `%p` is fine except the argument should be `void *` rather than `char *`, but GCC and MSVC appear not to warn about that. Printing `string2` with `%s` is fine. – Eric Postpischil Mar 16 '22 at 10:44
  • GCC warns if you write `printf("%s", 'A');`... – the busybee Mar 16 '22 at 11:42
  • How is that relevant to the question? There is no `printf` of a character with `%s` in it. – Eric Postpischil Mar 16 '22 at 11:54
  • See the last paragraph of the question... – the busybee Mar 16 '22 at 12:30