0

A char pointer can be assigned an arbitrary string but an integer pointer cannot be assigned an integer. Since both of them are pointers and contains address. Why is assigning string valid but an integer invalid in C to a pointer before dynamic allocation.

#include<stdio.h>

int main()
{
        char *s = "sample_string"; // valid
        printf("%s\n", s);
        int *p = (int)5; // invalid
        printf("%d\n", *p);
        return 0;
}

Which gives output :

sample_string
Segmentation fault (core dumped)

What is the reason behind it? Although both of them are invalid in C++.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • `"sample_string"` is pointer it is called as literal but `(int)5` is not – kiran Biradar Feb 12 '20 at 06:40
  • "sample_string" is a pointer. How? can you please explain me a bit more I am a beginner –  Feb 12 '20 at 06:41
  • https://stackoverflow.com/questions/2589949/string-literals-where-do-they-go – kiran Biradar Feb 12 '20 at 06:45
  • I took the liberty of removing the C++ tag. Your source is plain C (indeed, including `` would be deprecated in C++), and the type of a string literal is one of the points where the two languages differ (C is `char[]`, C++ is `const char[]`, which is the reason why C++ balks at assigning that to a non-`const` pointer.) – DevSolar Feb 12 '20 at 08:00

5 Answers5

4

There is no "string type" in C. A "string", by C definition, is an array of char with a zero byte at the end.

The type of "sample_string" is char[14], which can be assigned to a pointer.

The type of (int)5 is int, which cannot[1].

The segmentation fault happens because you are accessing the address 0x00000005, which is not valid.


[1]: Technically you can. But if you want to dereference that pointer successfully, you have to take care that the address value of that integer has the proper alignment for the type, and is referring to a valid object of the type. Which is why compilers generate a warning if you don't explicitly cast that integer to pointer type in the assignment, to indicate that you do know what you're doing.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • ok i got it, but my question is why is that where is the string "sample_string" kept. Is it stored in the heap section?\ –  Feb 12 '20 at 06:47
  • 1
    @PulkitBhatnagar: That is not the question you asked. See the comment by kiran Biradar for that answer. – DevSolar Feb 12 '20 at 06:48
  • pardon me, but could you please explain me where actually it is stored heap or stack? Kiran biradar suggestion does not explain this –  Feb 12 '20 at 06:50
  • 2
    @PulkitBhatnagar: Yes, [his link](https://stackoverflow.com/questions/2589949/string-literals-where-do-they-go) does answer *exactly* that question. – DevSolar Feb 12 '20 at 06:51
  • 1
    @PulkitBhatnagar: The string is stored where the compiler puts it — it is often in the text segment so that attempts to modify it will fail (and usually cause the program to crash). – Jonathan Leffler Feb 12 '20 at 06:51
  • 1
    @PulkitBhatnagar No, it's not on heap, there's no dynamic allocation here. You can confirm this on godbolt – theWiseBro Feb 12 '20 at 06:52
  • @PulkitBhatnagar Read the CiroSantilli answer it is more clearer. – kiran Biradar Feb 12 '20 at 06:52
  • I am sure lacking concepts. I am sorry if it was too basics. thank you guyz –  Feb 12 '20 at 06:55
  • 1
    Nice clarification. – chux - Reinstate Monica Feb 12 '20 at 14:56
1

char *s = "sample_string"; Here "sample_string" is a string literal which is a const char[] in C++. It's implicitly converted to const char*. You'll get a warning though since you're assigning it to a char*.

int *p = (int)5; Here 5 is just an integer. Since you're assigning this a pointer, that means it's an invalid pointer value. And hence when it's referenced, you get a segfault.

theWiseBro
  • 1,439
  • 12
  • 11
0

The convention is that strings are arrays of char (char[]) and a pointer to a string points to the first element of this char array, similar like a pointer to an array always points to its first element by default, i.e for an int array

 int a[10];
 int *p;
 p=&a 

points to the first element of a that is a[0] in index notation

ralf htp
  • 9,149
  • 4
  • 22
  • 34
0

This is simple:

  • A char object may hold a char value: char x = 'a';.
  • An int object may hold an int value: int x = 3;.
  • A char * object may point to an array of char: char *p = "abc";.
  • An int * object may point to an array of int: int *p = (int []) {1, 2, 3};.

(In this answer, “point to an array” is short for “point to the first element of an array”.)

In C, a string literal, such as "abc", is effectively an array of char, including a null character at the end. Also, the text above, (int []) {1, 2, 3}, is a compound literal that creates an array of int. So both "abc" and (int []) {1, 2, 3} are arrays. When an array is assigned to a pointer, the C implementation automatically converts it to a pointer to its first element. (This conversion occurs whenever an array is used in any expression other than as the operand of sizeof, as the operand of unary &, or, if it is a string literal, as the initializer for an array.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • like a string_literal is a constant, what about the compound literal is it also constant. Also are both of them are stored in the same `.rodata` section? –  Feb 12 '20 at 12:51
  • 2
    @PulkitBhatnagar: For historical reasons, the C standard does not define the behavior when a program attempts to modify a string literal, but it does not say it is read-only or constant. Compound literals can be modified (unless defined with `const`). Some C implementations store string literals in `.rodata` section. Some store them elsewhere. Some may store compound literals in a `.rodata` section if it is possible in the circumstances. Some may store them elsewhere or construct them during program execution. `.rodata` is part of something some computer systems use; it is not built into C. – Eric Postpischil Feb 12 '20 at 12:55
0

but an integer pointer cannot be assigned an integer.

Not quite. In C an integer can be assigned to a pointer - with certain conditions. Yet this only sets the pointer to 5, not that p points to an int with the value of 5. *p attempts to read what is at address 5 and interpret that location as an int. Certainly access to address 5 is invalid and causes a seg fault.

Even if those conditions are met (see below), this is certainly not what OP is seeking which I assume to be set the pointer p to point to someplace with the value/type of 5/int in it.

(int) {5} is a compound literal, available since C99. Here it is an int with the value of 5 and code takes the address of that object and assigns that address to p.

 // int *p = (int)5;
 int *p = & ((int) {5});
 printf("%d\n", *p);  // prints 5 

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. C17dr § 6.3.2.3 5

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256