-1

i was messing around with pointers in C and i came across something like this

#include <stdio.h>

int main() {

    char *str2 = "Heyya";
    printf("%d %d %s\n", &str2, str2, str2);
    return 0;
}

the program ran successfully and gave output

6422300 4214884 Heyya

what I didn't understand is that how come the program printed "Heyya" without using * operator in the second "str2"(the one that is putting value to %s) in the printf function

PS when I run the same with *str2 it gives a segmentation fault

can anyone explain what is happening in the memory?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • For format specifier `%s`, `printf` expects an address to `char`. Dereferencing a pointer to `char` would result in a `char` value (i.e. `*str2` would result in `'H'`). A segmentation fault occurs because `'H'` is not a valid address. – Fiddling Bits Dec 06 '19 at 14:39
  • 1
    Printing `&str2` and `str2` using the `%d` format gives undefined behaviour, since neither `&str2` not `str2` are of type `int`, and `%d` tells `printf()` to assume they are. The reason `str2` is printed using `%s` is because `%s` means that the argument is the address of the first character in a nul (zero) terminated string - which is the case. – Peter Dec 06 '19 at 14:43
  • 1
    Please read [this](https://stackoverflow.com/questions/57842756). – n. m. could be an AI Dec 06 '19 at 14:43

4 Answers4

3

str2 is a pointer to a character-array which is a literal constant located in the code segment. It is not "allocated." It is simply part of the program's object-code.

Your printf() call now prints the following three things:

  1. The address of the str2 pointer variable itself, which is 6422300.
  2. The address of the character array in the code segment, pointed-to by the pointer at 6422300, which is 4214884.
  3. The bytes that are located at address 4214884, presented as a string.
Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
  • Can you address segmentation fault? – Fiddling Bits Dec 06 '19 at 14:46
  • Actually, `str2` is a pointer to the first character in an array. The string literal initialiser means that `str2` points to the first character of a statically allocated array. `str2` is not a pointer to an array – Peter Dec 06 '19 at 14:46
3

For starters this call

printf("%d %d %s\n", &str2, str2, str2);

invokes undefined behavior because there are used incorrect conversion formats for pointers.

A correct call can look like

printf("%p %p %s\n", ( void * )&str2, ( void * )str2, str2);

As for the output then the expression &str2 gives the address of the local variable str2. The expression str2 gives the address of the first character of the string literal "Heyya" that has the static storage location.

If to use the above expression with the conversion format %p then the address will be outputted. If to use the above expression with the conversion format %s then the string first character of which pointed to by the expression str2 will be outputted.

You should understand that the address of the variable str2 itself is different from the address of the string literal pointed to by the variable. That is the expression &str2 yields the address of the variable itself. The expression str2 yields the value stored in the variable that in turn is the address of the first character of the string literal.

As for your question

How is memory allocated in this program?

then in this declaration

char *str2 = "Heyya";

there is created a string literal "Heyya" with the static storage duration and that has the type char[6] (in C++ it has the type const char[6]) and a local variable str2 with the automatic storage duration that is initialized by the address of the first character of the string literal.

PunyCode
  • 373
  • 4
  • 18
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • The `(void *)` casts are unnecessary and may suppress warnings on some real errors. – Lee Daniel Crocker Dec 06 '19 at 18:02
  • @LeeDanielCrocker Without the cast some compilers issue errors. – Vlad from Moscow Dec 06 '19 at 18:03
  • Not if they're to spec. If a function declares an argument type of `void*` (as printf implies with %p), then any pointer type can be passed, but if you tried to pass, say, an int, it would warn (which is good). If it warns you when passing an `int*`, then your compiler is broken (or perhaps it's set to expect C++ or a different version of C?) – Lee Daniel Crocker Dec 06 '19 at 18:08
  • @LeeDanielCrocker www,ideone.com, language C99, the program #include int main(void) { int x = 10; printf( "%p\n", &x ); return 0; } the compilation error prog.c:7:12: error: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Werror=format=] – Vlad from Moscow Dec 06 '19 at 18:12
  • I believe you, I'm just saying it's not supposed to do that, and there's a good reason it's not supposed to do that. I'd be curious as to what exact compiler and settings are used by ideaone. – Lee Daniel Crocker Dec 06 '19 at 18:15
3

str2 is a pointer to a location in the memory where "Heyya" was stored. printf("%s", strpointer) will print the string pointed to by strpointer, until it reaches null terminator, which is what makes it a string. If you add '*' before str2, it will print only the value of the address str2 points at, which is "H". That's happening because '*p' is not a pointer, but it's the actual value of the address of p, but 'p' is a pointer and printf will print the string from the address of which p points to, untill Null Terminator.

Alon Barenboim
  • 428
  • 3
  • 11
1

printf is a function that let you print something from values given as supplementary arguments. something means some representation from the value.

For instance:

%d takes the corresponding value and write it as a decimal number. You gave first &str2 which is the address of the pointer str2. Second you gave str2 which is the value stored in str2, the address of a C-string. Note, that pointers must be print with %p not %d, but that is almost the same reasoning.

%s is more subtle as it takes an address where a C-string must be stored and print every characters of that C-string.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69