why does the first one prints the string value whereas second give segfault?
What's happening in Case I:
The type of staticArray is char [100] i.e. array of 100 char.
The type of &staticArray is char (*)[100].
The %s format specifier in scanf() expect the argument as a pointer to initial element of char array i.e. of type char *.
You are passing char (*)[100] type to scanf(), hence compiler is giving warning on this statement.
The &staticArray give you pointer to the array of type char (*)[100] which is numerically same as the base address of array.
Consider this example:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
Output:
## ./a.out
staticArray: 0x7ffee4044a70
&staticArray : 0x7ffee4044a70
staticArray and &staticArray both yield a pointer to the same address1) but their type is different.
That's why when you pass &staticArray to scanf(), getting warning during compilation due to type mismatch but when scanf() called, it treat that pointer as char * and read input and store the result to given location. When printing it later, it prints the string value.
What's happening in Case II:
The type of dynamicArray is char *.
The type of &dynamicArray is char **.
So, you are passing char ** type to scanf() which expects char * when %s format specifier is used. Hence compiler is giving warning on this statement.
The pointer &dynamicArray is different from dynamicArray.
Consider this example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
Output:
## ./a.out
dynamicArray: 0x7fd615401690
&dynamicArray : 0x7ffee7ab7ad0
dynamicArray and &dynamicArray both yield different pointer.
When you pass &dynamicArray to scanf() (which read input and store the result to given location), it lead to undefined behavior2) because your program end up accessing invalid memory.
When you pass &dynamicArray to printf() with format specifier %s, printf(), it access that address to write the character string and end up accessing invalid memory, lead to undefined behavior2). Hence, you are getting segfault.
1) An array is automatically converted to a pointer to its first element but there are few exceptions to this rule (C11 Standards#6.3.2.1p3):
- The array is the operand of
sizeofoperator. - The array is the operand of
_Alignofoperator. - The array is the operand of
&. - The array is a string literal used to initialize an array.
2) An undefined behavior includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.
Answer from H.S. on Stack Overflowwhy does the first one prints the string value whereas second give segfault?
What's happening in Case I:
The type of staticArray is char [100] i.e. array of 100 char.
The type of &staticArray is char (*)[100].
The %s format specifier in scanf() expect the argument as a pointer to initial element of char array i.e. of type char *.
You are passing char (*)[100] type to scanf(), hence compiler is giving warning on this statement.
The &staticArray give you pointer to the array of type char (*)[100] which is numerically same as the base address of array.
Consider this example:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
Output:
## ./a.out
staticArray: 0x7ffee4044a70
&staticArray : 0x7ffee4044a70
staticArray and &staticArray both yield a pointer to the same address1) but their type is different.
That's why when you pass &staticArray to scanf(), getting warning during compilation due to type mismatch but when scanf() called, it treat that pointer as char * and read input and store the result to given location. When printing it later, it prints the string value.
What's happening in Case II:
The type of dynamicArray is char *.
The type of &dynamicArray is char **.
So, you are passing char ** type to scanf() which expects char * when %s format specifier is used. Hence compiler is giving warning on this statement.
The pointer &dynamicArray is different from dynamicArray.
Consider this example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
Output:
## ./a.out
dynamicArray: 0x7fd615401690
&dynamicArray : 0x7ffee7ab7ad0
dynamicArray and &dynamicArray both yield different pointer.
When you pass &dynamicArray to scanf() (which read input and store the result to given location), it lead to undefined behavior2) because your program end up accessing invalid memory.
When you pass &dynamicArray to printf() with format specifier %s, printf(), it access that address to write the character string and end up accessing invalid memory, lead to undefined behavior2). Hence, you are getting segfault.
1) An array is automatically converted to a pointer to its first element but there are few exceptions to this rule (C11 Standards#6.3.2.1p3):
- The array is the operand of
sizeofoperator. - The array is the operand of
_Alignofoperator. - The array is the operand of
&. - The array is a string literal used to initialize an array.
2) An undefined behavior includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.
Removing the & operator in both examples will solve the warnings. I'm not sure what your intended behavior is, but they seem to work correctly upon moving the & operator. This is because arrays are inherently pointers to the first element of the array so adding & is not what you want.
Working examples(exactly the same expect for &):
char staticArray[100];
scanf("%s",staticArray);
printf("%s\n", staticArray);
and
char* dynamicArray;
dynamicArray = (char*) malloc(sizeof(char)*100);
scanf("%s", dynamicArray);
printf("%s\n", dynamicArray);
Size of pointer is machine specific (whether it is 32-bit or 64-bit). The result would be 12 and 8 bytes respectively on 32 bit machine. For 64-bit machine, answer would be 16 and 8 bytes.
See the explanation
typedef struct {
int row; // 4 bytes
int col; // 4 bytes
char* data; // 4/8 bytes on 32/64-bit machine
}item1 ;
Total size = 12/16 bytes on 32/64 bit machine.
typedef struct {
int row; // 4 bytes
int col; // 4 bytes
char data[]; // 0 bytes --> Flexible array
}item2 ;
Total size = 8 bytes.
Why size of flexible array is 0?
C11: 6.7.2.1 (p18)
[...] In particular, the size of the structure is as if the flexible array member were omitted [...]
typedef struct item2 {
int row;
int col;
char data[];
}
in this struct item2 we have 2 ints, so the size will be 2*sizeof(int) in most of the systems, and also we have an array char data[] with undefined size so it counts as zero in this case, I think if there is padding in the struct then the amount of elements that the array will store will be related with the pading, but I am not sure.
total= 8 bytes.
typedef struct item1 {
int row;
int col;
char* data;
}
In this struct we have 2 ints that means 8 bytes ocupped by ints, and a pointer in a 64 bit system that means another 8 bytes.
total= 16 bytes.
There are a few things you need to know, there is no padding in this case an neither in
item2. and the diferrence between char* data; and char data[]; is that the last one is an array that will be allocated in the stack, and the first one is a pointer allocated in the stack that will be commonly used with dynamic memory from the heap.
Need help creating a dynamic char array in C - Stack Overflow
Is my understanding of dynamically allocating arrays in C correct?
char - Malloc array of characters dynamic vs static C - Stack Overflow
Dynamic vs dynamically created arrays in C - Stack Overflow
Videos
This line arr = (char*)malloc (2 * sizeof (char)); will allocate memory for 2 bytes only. But you are overwriting the memory by accessing the more 8 or more than 8 byes. If you access more than two byes means, it will give some unpredictable issue. In case you want more memory please follow the below code.
#define USER_SIZE 10
arr = (char*)malloc ( USER_SIZE * sizeof (char));
Assign the value in USER_SIZE macro and then allocate the memory as much as you want.
Example for 2D pointer ( 5 X 10 )
#define ROW 5
#define COLUMN 10
main()
{
unsigned char **p = NULL, colum = 0;
p = malloc ( ROW * sizeof ( unsigned char *) );
for (;colum< ROW; ++colum )
{
p[colum] = malloc (COLUMN * sizeof (unsigned char ));
}
}
What you are doing is called buffer overflow by writing beyond the bounds of memory allocated by malloc call. The compiler doesn't do bounds checking (it assumes you know what you are doing, and you only pay for what you use) and allow you to compile and run. However, it will lead to undefined behaviour and your program may crash. You shouldn't rely on such behaviour.
You, the programmer, has to make sure that you don't do illegal memory access. You should not cast the result of malloc. Also, malloc can fail to allocate memory in which case it returns NULL, the null pointer, which you should take care of. You can combine the two statements into one.
int length = 8; // you can also use a macro
char *arr = malloc(length * sizeof *arr);
if(arr) {
// malloc call successful
// do stuff with arr
}
I was going through an example of C code, and I was trying to figure out WHY we have to dynamically allocate an array rather than statically allocate in a specific example. I will write the example in pseudo code as it is simple and the code is not the point of this question:
obtain user input using scanf method and store in variable of type int n
Create an array int A[n]
Is my logic sound for why this is wrong:
This is wrong because the compiler has to decide the size of the function stack. In order to asses the size of the function stack, it will observe each of the variables in the function. However, since the value of n will only be determined at runtime, we cannot determine how much stack memory is needed for array A because the size will only be determined at run time. As a result, we must dynamically allocate memory.
Welcome to Stack Overflow! Coincidentally, the main problem with your code is that it is vulnerable to a stack overflow. scanf has no way of knowing how big userInput is, because you didn't tell it, and will happily continue filling memory long past the end of your very short array.
If you want to capture exactly three characters (with no nul terminator), use scanf("%3c", userInput) instead. Note that without the NUL, you must not expect to treat userInput as a string; printing it via printf for example will result in a random amount of gibberish owing to the fact that C does not know where the string ended.
Now, to answer your actual question on "what's the difference between malloc and the static array": the difference is of scope. If you only ever use userInput before its creating function returns, there is no practical difference, but you're in trouble the minute you try to do something like this:
int function1 {
char my_string[3];
scanf("%3c", my_string);
return my_string; /* WRONG! DANGER! */
}
The return in the above example will happily return the pointer to my_string to the calling function. However, as soon as function1 returns, the stack is rolled back and the memory my_string occupied is essentially gone (and likely already re-used). The results are unpredictable but almost universally very bad for your program.
However, had you used malloc() instead, you could safely return the my_string pointer and the memory would persist until someone later called free(my_string) (where my_string is the pointer to the original my_string; it need not be named the same!).
This highlights another difference: with a stack variable such as char my_string[3];, you do not need to worry about (and indeed cannot) free() the memory, where as if the memory is malloc()'d instead, you must free() it if you wish to reclaim the memory.
There are some nuances to the above, such as file-scoped variables and static function variables, which I leave as topics for further reading.
As pointed in Giorgi's answer, the main problem is the incorrect usage of the address-of operator &.
However, the reason why it worked on one case and why it didn't work on another is very interesting.
char array[3]: When you declare that array, memory space will be allocated for it andarraywill be a label to that location(memory address). When you passarraytoscanf(or use it anywhere else without subscripting[]), you're passing an address to that function. Because of that, when you use the&operator on the labelarray, it returns the same address to you BUT with different type (T(*)[3]), which your compiler probably complained about. But, as the memory address is valid, it worked as expected.char *array = malloc(): When you declare that variable, memory is also reserve for it, but this time in a different place and the space reserved issizeof T(*), so it can hold a memory address. This variable also has an address in memory, which you can also get using&array. Then youmallocsome memory andmallocreturns to you an address of a memory block which you can now use. You can get that memory address by simply doingarray. So, when you callscanfwith the&arrayyou're passing the variable address instead of the block address. That's why it crashes (I'm guessing you were not entering only two characters).
Check this code:
#include <stdio.h>
#include <stdio.h>
int main(void)
{
char *array[3];
char *ptr = malloc(3 * sizeof(char));
printf ("array : %p\n", array);
printf ("&array: %p\n\n", &array);
printf ("ptr : %p\n", ptr);
printf ("&ptr : %p\n", &ptr);
scanf("%s", &ptr);
printf ("ptr : %p\n", ptr);
return 0;
}
Which outputs:
$ ./draft
array : 0x7ffe2ad05ca0
&array: 0x7ffe2ad05ca0
ptr : 0x19a4010
&ptr : 0x7ffe2ad05c98
ABCD
ptr : 0x44434241
scanf got the address of the pointer, so when it saves the value it reads from stdin, it overwrites the address we had from malloc! The memory block we had is now gone, memory is leaking... Now, this is bad because we're overwriting stuff on our stack, memory is leaking, and it will crash.
Observe the last output: the value of ptr (which previously was the address of an allocated block) is now 0x44434241 (DCBA, ASCII Table)! How nice is that?
When the professor uses word dynamic it means that an array can change its size on the fly. That is new elements can be added to or deleted from the array. A dynamically allocated array means the allocation of an array at run-time in the heap. Statically allocated arrays are allocated before the main function gets the control.
Take into account that C has Variable Length Arrays (VLA). Bit it is not the same as dynamic arrays. VLA means that an array may be recreated with different sizes. But in each such recreation you create a new array.
An example of a dynamic array is standard C++ class std::vector.
The answer to this question will depend on how pedantially one wants to treat terms like "array" and "dynamic". Is "array" supposed to refer exclusibely to array types? Or are we allowed to include malloc-ed arrays as well, accessible through pointers? Does "dynamic" refer to dynamic memory (even though the standard C nomenclature does not use this term)? Or are we allowed to consider local VLAs as "dynamic" as well?
Anyway, one can separate arrays into three conceptual categories
- Arrays with compile-time size
- Arrays with run-time initial size, which cannot be resized
- Arrays with run-time initial size, which can be resized
Apparently, your professor referred to the second category as "dynamically created arrays" and to the third category as "dynamic" arrays.
For example, arrays from the first category are the classic built-in C89/90-style C arrays
int a[10];
Arrays from the second category are C99 VLAs
int a[n];
(or new-ed arrays in C++).
Arrays from the third category are arrays allocated with malloc
int *a = malloc(n * sizeof *a);
which can be later resized with realloc.
Of course, once we step beyond the built-in features of the core language, the division between these categories becomes purely conceptual. It is just a matter of the interface the array implementation offers to the user. For example, it is possible to implement arrays from the third category through arrays of the second category, by destroying the old fixed-size array and allocating a new one of different size. In fact, that is how realloc is allowed to work in general case.
hey! I am stuck on this question, I have to cin and cout a dynamic array of characters (not using library function/ c++ string types), here are the two issues i am facing:
-
I do not know how long the name would be so should I just take a precondition that it should be smaller than let's say 100? or is there a way that I can create a dynamic array without specifying coloum size?
-
this code that i came up with is producing weird result and i have no clue how to correct it T_T
I would be really thankful if you all can help me with this T_T.
my needed output should look something like:
enter name #1: abc def
enter name #2: ghi jkl...
.
.
.
enter name #n: nnn mmm
int main()
{
int n, j=0;
cout<<"How many names do you want to enter ? ";
cin>>n;
char** name = new char*[n];
for(int i=0; i<n; i++)
{
name[i]=new char[100];
}
for(int i=0; i<n; i++)
{
cout<<"enter name #"<<i+1 <<" :";
do
{
cin>>name[i][j];
j++;
}while(name[i][j]!='\n');
}
for(int i=0; i<n; i++)
{
for(int j=0; name[i][j]!='\n' ; j++)
{
cout<<name[i][j];
}
cout<<endl;
}
}Edit: Thank You so much for helping me with this problem however I figured a way to do it, it's definitely not the best or the most useful but our professor won't vibe with any other straight ways lmao here's what I came up with and the output I get, please let me know what yall think!
int main()
{
int n;
cout<<"How many names do you want to enter ? ";
cin>>n;
char** lastname = new char*[n];
for(int i=0; i<n; i++)
lastname[i]=new char[100];
char ** firstname = new char*[n];
for(int i=0; i<n; i++)
firstname[i]=new char[100];
for(int i=0; i<n; i++)
{
cout<<"enter name #"<<i+1 <<" :";
cin>>firstname[i]>>lastname[i];
}
for(int i=0; i<n; i++)
{
cout<<firstname[i]<<" "<<lastname[i];
cout<<endl;
}
}
/* OUTPUT :
How many names do you want to enter ? 3
enter name #1 :Fucker Certified
enter name #2 :Flex Offender
enter name #3 :Billy Balls
Fucker Certified
Flex Offender
Billy Balls
*/I am pretty sure it's not the most efficient but this was all I could think of T_T
once again Thank You so muchhh!!
There are several flavors of arrays, depending on how and where they are declared.
Fixed-length Arrays
Fixed-length arrays must have their size determined at compile time. You cannot change the size of a fixed-length array after it has been defined.
Fixed-length arrays are declared in one of the following ways:
T a[N];
T a[N] = { /* initializer list */ };
char_type a[N] = "string literal";
T a[] = { /* initializer list */ };
char_type a[] = "string literal";
In the first three cases, N must be a constant expression whose value must be known at compile time. In the first three cases, the size of the array is taken from N; in the last two cases, it's taken from the number of elements in the initializer list or the size of the string literal.
The initial contents of a fixed-length array depend on its storage duration and whether an initializer has been supplied.
If the array has static storage duration (meaning it was declared at file scope outside of any function body, or was declared with the static keyword) and no initializer is present, then all of the array elements are initialized to 0 (for scalars) or NULL (for pointers). If T is an aggregate type such as a struct or an array type, then each member of the aggregate is initialized with a 0 or NULL. union types are similarly zeroed out.
If the array has auto storage duration (meaning it was declared within a function or block without the static keyword) and no initializer is present, then the contents of the array are indeterminate - basically, garbage.
If the array is declared with an initializer list (regardless of storage duration), then the initial values of the array elements correspond to the initializer. If there are fewer elements in the initializer than the array (for example, N is 10 but you only initialize the first 5 elements), then the remaining elements are initialized as though the array had static storage duration. IOW, given the declaration
int a[10] = {0, 1, 2};
then the initial contents of the array are {0, 1, 2, 0, 0, 0, 0, 0, 0, 0}.
Fixed-length arrays containing string values may be initialized using a string literal. C allows for "wide" character strings, so char_type may be either char or wchar_t. The rules are the same for regular initializer lists, except that N (if specified) must be at least 1 more than the length of the string to account for the string terminator.
This means that
char a[10] = "test";
will be initialized as {'t', 'e', 's', 't', 0, 0, 0, 0, 0, 0} and
char a[] = "test";
will be initialized as {'t', 'e', 's', 't', 0}.
Arrays with static storage duration are stored such that they are available as soon as the program is loaded, and aren't released until the program exits. This usually means that they're stored in a memory segment like .data or .bss (or the equivalent for whatever executable format your system uses).
Arrays with auto storage duration are stored such that they are allocated at block or function entry and released at block or function exit (in practice, they'll probably be allocated at function entry, regardless of whether they're limited to a smaller scope within the function) - this typically translates to the stack, although it doesn't have to.
Variable-length Arrays
Variable-length arrays were added in C99 - they behave mostly like fixed-length arrays, except that their size is established at run time; N does not have to be a compile-time constant expression:
int n;
printf( "gimme the array size: ");
scanf( "%d", &n );
T a[n]; // for any type T
Contrary to what their name implies, you cannot change the size of a variable-length array after it has been defined. "Variable-length" simply means that the size isn't fixed at compile time, and can change from definition to definition.
Since their size isn't set until runtime, variable-length arrays may not be declared at file scope or with the static keyword, nor can they be declared with an initializer list. Exactly how the space for VLAs is managed is up to the implementation; it may be (and usually is) taken from the stack, but AFAIK may be taken from somewhere else.
Dynamic Arrays
Dynamic arrays are not really "arrays" as such, at least in terms of the data types of the objects we use to manage them. Dynamic arrays are allocated at runtime using one of malloc, calloc, or realloc, and that storage is held until released with a call to free.
T *p = malloc( sizeof *p * N ); // where N may be either a compile-time or
// run-time expression
...
free( p );
A dynamic array may be resized using the realloc library function, like so:
/**
* If realloc fails, it will return NULL and leave the original array in
* place. We assign the result to a temporary variable so we don't risk
* losing our only reference to that memory.
*/
T *tmp = realloc( p, sizeof *p * new_size );
if ( tmp )
p = tmp;
While the memory for the array elements themselves is taken from the heap (or whatever dynamic memory pool), the memory for the pointer variable p will be allocated from either a .bss or .data segment or from the stack, based on p's storage duration (static or auto).
Memory allocated with malloc or realloc is not initialized; the contents of that memory will be indeterminate. Memory allocated with calloc will be initialized with zeros.
Arrays vs. Pointers
At some point, somebody is going to tell you that "an array is just a pointer". That person is not correct.
When you declare an array (either fixed- or variable-length), enough storage is set aside for the elements of that array and nothing else; no storage is set aside for any metadata such as the array length or a pointer to the first element. Given the declaration
T a[N];
then the storage will look something like this:
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[N-1]
+---+
There is no object a apart from the array elements themselves (or, more properly, the object a is the elements of the array), and the expression a may not be the target of an assignment.
But...
The expression a[i] is defined as *(a + i); that is, given a pointer value a, offset i elements (not bytes!) from that address and dereference the result. But if a is not a pointer, how can that work?
Like this - except when it is the operand of the sizeof or unary & operators, or is a string literal used as an array initializer in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
This has several implications:
- The expressions
a,&a, and&a[0]will all yield the same value (the address of the first element of the array), but the types of the expressions will be different (T *,T (*)[N], andT *, respectively); - The subscript operator
[]works equally well with both array expressions and pointer expressions (indeed, it's defined to work on pointer expressions); - When you pass an array expression to a function, what you are actually passing is a pointer value, not the entire array;
For dynamic arrays, the situation is different. Given the line
T *p = malloc( sizeof *p * N );
then your storage will look something like this:
+---+
p: | | ---+
+---+ |
... |
+------+
|
V
+---+
| | p[0]
+---+
| | p[1]
+---+
...
+---+
| | p[N-1]
+---+
In this case, p is a separate object from the array. Thus, &p won't give you the same value as p and &p[0], and its type will be T ** as opposed to T (*)[N]. Also, since p is just a pointer variable, you can assign a new value to it (although if you do so without freeing the memory it points to first, you'll create a memory leak).
Similarly, sizeof p won't behave like sizeof a; it will simply return the size of the pointer variable, not the size of the allocated memory that the pointer points to.
Static arrays are allocated memory at compile time and the memory is allocated on the stack. Whereas, the dynamic arrays are allocated memory at the runtime and the memory is allocated from heap.
This is static integer array i.e. fixed memory assigned before runtime
int arr[] = { 1, 3, 4 };
This is dynamic integer array i.e memory assigned on runtime
int* arr = new int[3];
Hi there! How do C programmers work with dynamically allocated arrays – i.e vectors as in std::vector – in real C codebases, where dynamic allocations are possible (that is, there is heap memory and enough memory etc.)?
I keep finding myself wanting to do something like: struct vec { int* ptr; size_t len, cap; } and a bunch of other functions to create such a vector, push to it etc. If I were not to do this, I'd have to pass to many functions int** ptr, size_t* len, size_t* cap, which is very cumbersome.
None of the two methods above feel very C-like, given that there is no proper metaprogramming and that this approach seems like a too hefty abstraction for C but again, I don't have experience with real codebases, production code. In some situations I find that I can reduce the number of parameters, but not all.
What do you think? What is the solution? Do you have other approaches? Have you encountered this? If not, why?
Thank you very much for your input!
P.S. On mobile. If code formatting is broken, I'll fix it later. Also, the C23 changes which add some kind of generics using macros should not affect the answers here, as far as I can think; this question is in its essence concerned with abstraction in C and how it is approached in C.