-4
int aryint[4] = {1,2,3,4};
char *ptr = "1234";
char ch ='a'; 
char *chptr = &ch;

//chptr =  3509449623 (mem addr)
printf("chptr =  %u,  chptr);

//aryint =  3509449648 (mem addr)
printf("aryint =  %u ", aryint);

//ptr =  1234 
printf("ptr =  %s, ptr);

Why would printing out a char point “ptr” return an entire array of char (the whole string), and printing out a char point “chptr” return the mem addr of “chptr”?

If this is because “ptr” is pointing to an array, then why printing out the array “aryint” only return the mem addr of aryint (not the entire array)? So printing out entire array only applies to string constant? Or is it because of the %s?

But when I tried replacing the %s with %u on the printf() of ptr, I also get a constant (4197008) which is equivalent to the entire array/string (1234), and not the mem address:

//ptr u =  4197008 (a constant not mem addr), ptr s = 1234,
printf("ptr u =  %u, ptr s = %s”, ptr, ptr)

However, when I attempt to print out char array “str”, I get the mem address when I applied the %u on “str” (not the entire array as in ptr). But I got the entire array printed again when %s is applied on “str”, and not the mem address as in chptr and aryint previously.

char str[5] = "1234"; 
//str u = 3509449696 (mem addr), str s = 1234
printf("str u = %u,  str s =%s”, str, str );

This seems a bit strange to me. Is there any other weird phenomena that I should be aware of when coding in C? I am a newbie.

Any help will be greatly appreciated!

Chloe
  • 47
  • 5

4 Answers4

1

printf expects a string called the format string containing format specifiers. These are parsed by printf (and denoted by a leading '%'). Whenever one is encountered, printf gets the next argument from the number of arguments passed and "applies" the meaning of the format specifier to the argument.

Example:

printf("%d", 1);

In the uppper example, the format specifier "%d" is encountered, which has its own meaning: it expects an argument of type int. 1 is an int, so the program is well-defined and fine.

Why would printing out a char point “ptr” return an entire array of char (the whole string) [...]

Because that's how the "%s" format specifier works. It expects a char* and prints all chars until a null byte ('\0') is found.

[...] and printing out a char point “chptr” return the mem addr of “chptr”?

It's undefined behavior because format specifier (expecting an unsigned int) and argument type (char*) do not match and there's no implicit conversion between both. It's simply undefined by the standard.
Beware: that's what the standard says. Remember that the standard just describes an abstract machine. The concrete machine does behave within the scope of said abstract machine but while the abstract machine defines a set of possible outcomes by "undefined," the concrete machine manifests real behavior. That real behavior depends on all that stuff beneath the standard (OS on a hosted implementation and hardware) but that's what roughly happens for real in printf("chptr = %u, chptr); on common machines:

  1. The leading part "chptr = " is printed.
  2. The percentage sign is encountered, the "%u" is parsed.
  3. %u means unsigned int, so an unsigned int is popped off the argument list. printf doesn't know the exact types of the arguments because it uses a variable argument list. It is type-unsafe.
  4. sizeof(unsigned int) bytes are fetched, parsed as an unsigned int, and printed out. Whether sizeof(char*) == sizeof(int) is up to the implementation, so it may very well happen that too many/too few bytes are popped off and that crashes the whole program. It's undefined behavior, after all.

In the end, just keep in mind to always use the appropriate format specifier, not to use printf(user_defined_string) or puts(user_defined_string), and read the standard to find out about possible instances of undefined behavior.

Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
0

It's the %s specifier for a string of characters, which stops printing when it reaches a null character (\0). %u on the other hand, is the specifier for an unsigned decimal integer.

Read about printf() and format specifiers here. You should use %p to print pointer addresses.

anukul
  • 1,922
  • 1
  • 19
  • 37
0

ptr is pointing to an array of characters (string). When you do printf with a specifier %s you are telling the program that you expect to print a string, and so when you give it ptr, it prints out the string.

If you want to print a pointer value, use %p instead.

Lincoln Cheng
  • 2,263
  • 1
  • 11
  • 17
0

'ptr' is a pointer, and it has been initialised to point to a string constant. A string constant is accessed by a pointer to its first element (i.e. the first element of a character array).

if 'printf' receives a pointer to the beginning of a character array - it will access the string constant concerned and print the string ...

see Ritchie et al pg 87 'The C Programming Language'

Grant Shannon
  • 4,709
  • 1
  • 46
  • 36