I am trying to set an array of integer pointers. The programs is supposed to set the pointers at index i to point to an integer of value 2*i. The programs then should print out the pointees of the first 5 pointer elements, which should be 0,2,4,6,8.
For some reason I am getting a segmentation fault. Could anyone tell me why this happens and what I can do to fix it?
I attempted to replace the final line with " arr[index] = &i; ", which does not give me a segmentation fault but still gives me the wrong results.
Help would be greatly appreciated, just starting off array of pointers.
#include <stdio.h>
void setArr (int);
int * arr[10]; // array of 10 int pointers
int main(int argc, char *argv[])
{
int i;
setArr(0);
setArr(1);
setArr(2);
setArr(3);
setArr(4);
for(i=0; i<5;i++)
printf("arr [%d] = %d\n", i, *arr[i]); /* should be 0, 2, 4, 6, 8 */
return 0;
}
/* set arr[index], which is a pointer, to point to an integer of value 2*index */
void setArr (int index){
int i = 2 * index;
* arr[index] = i;
}
The problem is that you are not allocating memory for what each item in your array points to. The line
*arr[index] = i;
will set some random memory address (whatever was originally in arr[index]) to the value of i.
What you should do is:
void setArr(int index)
{
int *i = malloc(sizeof(int)); // allocate memory for the value
*i = 2 * index; // set the value
arr[index] = i; // make the array slot point at the value
}
but you need to make sure to free() the memory later. For example, before the return 0; statement in your main() function, put:
for (i = 0; i < 5; i++)
free(arr[i]);
You need to malloc space for your pointers inside the array.
This is taken from chapter 9 of Yashavant P. Kanetkar's Let Us "C" and should clarify why what you did earlier didn't work.
When we are using a two-dimensional array of characters we are at liberty to either initialize the strings where we are declaring the array, or receive the strings using scanf( ) function. However, when we are using an array of pointers to strings we can initialize the strings at the place where we are declaring the array, but we cannot receive the strings from keyboard using scanf( ). Thus, the following program would never work out.
main( )
{
char *names[6] ;
int i ;
for ( i = 0 ; i <= 5 ; i++ )
{
printf ( "\nEnter name " ) ;
scanf ( "%s", names[i] ) ;
}
}
The program doesn’t work because; when we are declaring the array it is containing garbage values. And it would be definitely wrong to send these garbage values to scanf( ) as the addresses where it should keep the strings received from the keyboard.
Solution
If we are bent upon receiving the strings from keyboard using scanf( ) and then storing their addresses in an array of pointers to strings we can do it in a slightly round about manner as shown below.
#include "alloc.h"
main( )
352 Let Us C
{
char *names[6] ;
char n[50] ;
int len, i ;
char *p ;
for ( i = 0 ; i <= 5 ; i++ )
{
printf ( "\nEnter name " ) ;
scanf ( "%s", n ) ;
len = strlen ( n ) ;
p = malloc ( len + 1 ) ;
strcpy ( p, n ) ;
names[i] = p ;
}
for ( i = 0 ; i <= 5 ; i++ )
printf ( "\n%s", names[i] ) ;
}
Here we have first received a name using scanf( ) in a string n[ ]. Then we have found out its length using strlen( ) and allocated space for making a copy of this name. This memory allocation has been done using a standard library function called malloc( ). This function requires the number of bytes to be allocated and returns the base address of the chunk of memory that it allocates. The address returned by this function is always of the type void *. Hence it has been converted into char * using a feature called typecasting. Typecasting is discussed in detail in Chapter 15. The prototype of this function has been declared in the file ‘alloc.h’. Hence we have #included this file.
But why did we not use array to allocate memory? This is because with arrays we have to commit to the size of the array at the time of writing the program. Moreover, there is no way to increase or decrease the array size during execution of the program. In other words, when we use arrays static memory allocation takes place.
Chapter 9: Puppetting On Strings 353
Unlike this, using malloc( ) we can allocate memory dynamically, during execution. The argument that we pass to malloc( ) can be a variable whose value can change during execution.
Once we have allocated the memory using malloc( ) we have copied the name received through the keyboard into this allocated space and finally stored the address of the allocated chunk in the appropriate element of names[ ], the array of pointers to strings.
This solution suffers in performance because we need to allocate memory and then do the copying
Related
Based on This Question Calculate Length of Array in C by Using Function i really need an explanation.
Let's say we have an Array like this:
int arr[] = {1,2,3};
here arr has the length 3, so passing into a Function will decay to Pointer and we lose track of its Length.
What happens if we Null terminate this array using '\0' like this:
int arr[] = {1,2,3,'\0'};
And pass it to a function like this:
void foo(int *arr){
int length = 0;
while(arr[length] != '\0'){
length++;
}
printf("Length = %d\n",length);
}
Is this ok?
I wrote the following code:
#include<stdio.h>
void foo(int *arr);
int main(void){
int arr1[] = {10,'\0'};
int arr2[] = {12,44,'\0'};
int arr3[] = {87,1,71,'\0'};
int arr4[] = {120,15,31,82,'\0'};
int arr5[] = {28,49,16,33,11,'\0'};
int arr6[] = {19,184,90,52,38,77,'\0'};
int arr7[] = {2,17,23,41,61,78,104,'\0'};
int arr8[] = {16,92,11,35,52,118,79,44,'\0'};
int arr9[] = {20,44,33,75,49,36,9,2,11,'\0'};
int arr10[] = {92,145,24,61,99,145,172,255,300,10,'\0'};
foo(arr1);
foo(arr2);
foo(arr3);
foo(arr4);
foo(arr5);
foo(arr6);
foo(arr7);
foo(arr8);
foo(arr9);
foo(arr10);
return 0;
}
void foo(int *arr){
int length = 0;
while(arr[length] != '\0'){
length++;
}
printf("Length = %d\n",length);
}
And i got the following Output:
Length = 1
Length = 2
Length = 3
Length = 4
Length = 5
Length = 6
Length = 7
Length = 8
Length = 9
Length = 10
Which prints the Length of all 10 arrays.
Now I'm confused here, because as far of my concern, as I read in some books, there is no way to make it work.
Why foo prints the length of all arrays?
It is illegal to use something like int arr[] = {1,2,3,'\0'}; ?
I know that if the Array has a 0 inside like this int arr[] = {1,2,0,3,4}; the length will be 2, but this is not my question.
This is how C-strings mark their end and length. And as they're just char arrays, naturally you can apply the same to other types of arrays as well.
Just remember that calculating the length of such an array through a pointer has a linear time complexity.
It is illegal to use something like int arr[] = {1,2,3,'\0'}; ?
No. It's perfectly legal. '\0' is an int which is same as 0. It's no different to using any number as marker to identify the end of the array. For example, you can use -1 if you array is going to contain only positive number. So your approach is valid.
The reason you wouldn't usually see in practice it's kind of needless to iterate over an array when you can simply pass it as an extra argument, which is easily understandable from maintenance point of view.
int arr[1024];
size_t len = sizeof arr/sizeof a[0];
func(arr, len);
void func(int *a, size_t length) {
}
Compare this with your approach.
Also, the size is calculated at compile-time whereas in your approach you have iterate over the array. Choosing the right sentinel could become difficult ( o or -1 or whatever) if it's also needed to be an element of the array.
Sidenote: '\0' is really 0 here, as your store ints.
You're using a sentinel. C-style strings have been using this method for decades to mark where the string finishes. It has the same benefits, but it also has the same drawbacks.
As long as you maintain the invariant that the sentinel occours only at the last place of the array you'll be able to get the length of the array. In O(N) time, as you have to traverse the sequence.
Note that you can shrink the sequence by terminating it earlier with a sentinel:
1 2 3 4 0 //
1 2 3 0 * // * as in: anything
But as soon as you do this, you cannot known the size of the array anymore. Even though you could technically append an extra element, a function without knowing the context cannot safely do this. In essence, you know the size of the sequence, but you don't known the size of the array anymore.
If you need a method to use to allow you to carry the array length with the array then try using one of these approaches.
Store the length in the start of the array
So (ideally) array[0], the first element would be a length.
The catch is that that only works if your array has a suitable type and the length fit in that type. You can in principle use union to define an element large enough to hold different types of data, including the length, but it's potentially wasteful.
Maintain a structure to store the array length and a pointer to the array data.
This is something like :
struct arrayinfo_s {
int length ;
char *data ;
};
char name[1000] ;
struct arrayinfo a ;
a.length = sizeof(name) ;
a.data = name ;
myfunc( &arrayinfo ) ;
There are many variations on this possible.
The "standard" convention.
As someone already mentioned, it is typical to track the array length and pass it as a separate parameter to the function.
myfunc( array, length ) ;
If array is a fixed size declared like e.g. int nums[100] ; then you can use sizeof(nums) if the variable was declared in the same function as you used sizeof() or globally.
There is also a variation on this for allowing a function to return an array of unknown length. Typically you would do something like returning a point to the array, but pass a parameter that is a pointer to some integer type to store the length of the new array in.
char *newstuff( int *newlength )
{
char *p = NULL ;
p = malloc( 102 ) ;
if( p == NULL )
{
*length = 102 ;
return p ;
}
else
{
*length = 0 ;
return NULL ;
}
}
I needed a character array containing a dynamic number of character arrays based on the number of files in a specific folder. I was able to accomplish this by initializing char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH] and then using FullPathNames = malloc( sizeof(*FullPathNames) * NumOfFiles * MAX_FILENAME_AND_PATHNAME_LENGTH ) ) after I know how many files another function discovered( which I have not provided). This process works flawlessly.
I can only use ANSI C; I am specifically using LabWindows CVI 8.1, to compile my code. I cannot use any other compiler. The below code is doing what I want. I can fill this array easily enough with the following code:
Strcpy(FullPathNames[0],”Test Word”);
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH];
size_t Size;
NumOfFiles = NumberOfUserFiles(“*.txt”, “C:\\ProgramData” );
FullPathNames = malloc( sizeof(*FullPathNames) * NumOfFiles * MAX_FILENAME_AND_PATHNAME_LENGTH ) );
Size = sizeof(*FullPathNames) * NumOfFiles;
Memset(FullPathNames,0,Size);
However, I would like to be able to pass FullPathNames which is an array of pointers to a variable amount of character arrays into a method. I want this method to be able to remove a single character array at a given index.
I am calling the method with the following code.
Remove_Element(FullPathNames,1, NumOfFiles);
The code for Remove_Element:
void Remove_Element( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN], int Index, int Array_Length )
{
int i;
char String[MAX_FILENAME_AND_PATHNAME_LEN];
char (*NewArray)[MAX_FILENAME_AND_PATHNAME_LEN];
int NewLength = Array_Length - 1;
size_t Size;
NewArray = malloc( sizeof( *NewArray) * NewLength * ( MAX_FILENAME_AND_PATHNAME_LEN ) );
Size = sizeof( *NewArray ) * NewLength;
memset(NewArray, 0, Size);
for ( i = Index; i < Array_Length - 1; i++ )
{
memcpy(String,Array[i+1],MAX_FILENAME_AND_PATHNAME_LEN); // Remove last index to avoid duplication
strcpy( Array[Index], String );
}
Array = NewArray;
}
My expectation of what I have currently is that the original data of FullPathNames remains except for the index that I removed, by copying data from index + 1, and the original pointers contained within FullPathNames is of course updated. Since I also wanted to shrink the array I attempted to set the array equal to the new array. The following information explains my attempts at debugging this behavior.
The watch variables present the following information as I enter the method.
FullPathNames = XXXXXX
NewArray = Unallocated
Array = XXXXXX
After I fill the new temporary Array the following happens:
FullPathNames = XXXXXX
NewArray = YYYYY
Array = XXXXXX
As I exit the method the following happens:
FullPathNames = XXXXXX
NewArray = YYYYY
Array = YYYYY
I was attempting to modify FullPathNames by passing it in as a pointer. I originally tried this task by using realloc but that just resulted in a free pointer exception.
Notes:
MAX_FILENAME_AND_PATHNAME_LENGTH = 516;
If I understand correctly, what you want to do is to modify the FullPathNames Pointer in the code part where you initialize your original array.
With your declartion of FullPatchNames
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH]
you basically declare a pointer to an array of MAX_FILENAME_AND_PATHNAME_LENGTH char elements. With your call to void Remove_Element(...) you just give a copy of this pointer to the local variable Array valid inside your function. Because of this Array = NewArray;, only changes the local copy of your pointer inside the function, not FullPathNames.
If you want to change the value of FullPathNames you must give a pointer to this pointer to your function. The Prototype of Remove_Element must look like this:
void Remove_Element( char (**Array)[MAX_FILENAME_AND_PATHNAME_LEN],
int Index, int Array_Length )
Now Array is a Pointer to an Pointer to an (one dimansional) array of char. By dereferencing this Pointer, you can change your original Pointer FullPathNames to point to your new object you created inside your function. You must modify the call to this function to Remove_Element(&FullPathNames,1, NumOfFiles);. To read from Array, you must dereference it using the * operator:
memcpy(String,*Array[i+1],MAX_FILENAME_AND_PATHNAME_LEN);
...
Array = NewArray;
Warning: This code will now produce a memory leak, since you are loosing your reference to your orignal object. You should remove this using the free() function somewhere in your code!
There seems to exist a certain lack of knowledge about the syntax in C language first and foremost.
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH]
This is one example. The syntax shown here would be read by a c- programmer as:
Semicolon is missing - maybe #define voodoo somewhere!
char (*FullPathNames)... - a function pointer! oh wait why square brackets next?!
Maybe he wanted to say char *FullPathNames; or he wanted char FullPathNames[MAX_FILENAME_AND_PATH_NAME_LENGTH]; Hm...
So here the first 101:
char foo[50]; // A fixed size array with capacity 50 (49 chars + '\0' max).
char *foo = NULL; // a uninitialized pointer to some char.
char (*foo)(); // a pointer to a function of signature: char(void).
char *foobar[50]; // This is an array of 50 pointers to char.
Depending on where your char foo[50]; is located (in the code file, in a function, in a structure definition), the storage used for it varies.
char foo1[50]; // zerovars section.
char foo2[50] = { 0 }; // initvars section
char foo3[50] = "Hello World!"; // also initvars section
void FooTheFoo( const char *foo )
{
if(NULL != foo )
{
printf("foo = %s\n", foo);
}
}
int main(int argc, const char *argv[])
{
char bar[50] = "Message from the past."; // bar is located on the stack (automatic variable).
FooTheFoo(bar); // fixed size array or dynamic array - passed as a (const pointer) in C.
return 0;
}
Now we got the basics down, lets look at 2-dimensional dynamic array.
char **matrix = NULL;
A pointer to a pointer of char. Or a pointer to an array of pointers to chars or an array of pointers to pointers to arrays of chars.
As lined out, there is no "meta" information regarding to what a char* or a char ** point to beyond that finally the dereferenced item will be of type char. And that it is a pointer to a pointer.
If you want to make a 2-dimensional array out of it, you have to initialize accordingly:
const size_t ROW_COUNT = 5;
const size_T COL_COUNT = 10;
char **myMatrix = malloc(sizeof(char *) * ROW_COUNT);
// check if malloc returned NULL of course!
if( NULL != myMatrix )
{
for(size_t row = 0; row < ROW_COUNT; row++ )
{
myMatrix[row] = malloc(sizeof(char) * COL_COUNT);
if( NULL == myMatrix[row] ) PanicAndCryOutLoudInDespair();
for(size_t col = 0; col < COL_COUNT; col++ )
{
myMatrix[row][col] = 0;
}
// of course you could also write instead of inner for - loop:
// memset(myMatrix[row], 0, sizeof(char) * COL_COUNT);
}
}
Last not least, how to pass such a 2-dimensional array to a function? As the char** construct does not contain the meta information regarding sizes, in the general (inner not a 0 terminated string) case, you would do it like that:
void FooIt( const char **matrix, size_t rowCount, size_t colCount )
{ // Note: standard checks omitted! (NULL != matrix, ...)
putchar(matrix[0][0]);
}
Last, if you want to get rid of your 2D dynamic array again, you need to properly free it.
void Cleanup2DArray( char **matrix, size_t rowCount )
{
for(size_t row = 0; row < rowCount; row++ )
{
free(matrix[row];
}
free(matrix);
}
The only thing more to say about it I leave to other gentle contributors. One thing coming to mind is how to express const-ness correctly for those multi-dimensional things.
const char **
const char const * const *
etc.
With this, you should be able to spot the places where you went wrong in your code and fix it.
The pointer you're passing is just a value. That it holds an address means you can dereference it to modify what it points to, but it doesn't mean changing its value directly (your assignment statement) will affect the caller-parameter. Like everything else in C, if you want to modify something by-address, then an address is exactly what you need to do it. If the thing you're modifying is a pointer, then the address of the pointer (through a pointer-to-pointer parameter) is the generally prescribed solution.
However, I can tell you the syntax and housekeeping to do that is... uninviting in your case. A simple pointer is easy enough, but a pointer-to-array-of-N isn't so simply. Were I you his would simply use the return result of the function itself, which is otherwise currently being unused and void. Declare your function like this:
char (*Remove_Element( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN],
int Index, int Array_Length ))[MAX_FILENAME_AND_PATHNAME_LEN]
{
....
return Array; // or whatever else you want to return so
// long as the type is correct.
}
and simply have the caller do this:
Array = RemoveElement(Array, Index, Array_Length);
A working variation of my solution appears below. The reason I had to do it this way is because while I was able to dereference (**Array)[MAX_FILENAME_AND_PATHNAME_LEN] I was only able to modify the first string array in the array.
The string array was initialized and filled several strings. While I could reference a string contained within *Array[0] but was unable to reference any of the other strings. The resulting array will replace the original array. This method will only work in the initial code block where the array to be replaced is initialized.
#define MAX_FILENAME_AND_PATHNAME_LEN MAX_FILENAME_LEN + MAX_PATHNAME_LEN
/*
This method was designed to free the memory allocated to an array.
*/
void FreeFileAndPathArrays( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN] )
{
free( Array );
}
/*
This method was designed to remove an index from an array. The result of this method will shrink the array by one.
*/
void Remove_Element( char (**ArrayPointer)[MAX_FILENAME_AND_PATHNAME_LEN],int Index, int *Array_Length, char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN] )
{
int i = 0;
int j = 0;
char String[MAX_FILENAME_AND_PATHNAME_LEN];
char (*NewArray)[MAX_FILENAME_AND_PATHNAME_LEN];
char (*GC)[MAX_FILENAME_AND_PATHNAME_LEN];
int Length = *Array_Length;
int NewLength = Length - 1;
size_t Size;
NewArray = malloc( sizeof( *NewArray) * NewLength * ( MAX_FILENAME_AND_PATHNAME_LEN ) );
Size = sizeof( *NewArray ) * NewLength;
memset(NewArray, 0, Size);
UI_Display("Test Block:");
for ( j = 0; j < NewLength; j++ )
{
if ( j != Index )
{
memcpy(String,Array[j],MAX_FILENAME_AND_PATHNAME_LEN);
strcpy( Array[Index], String );
Fill(NewArray,String,j);
UI_Display(String);
}
}
GC = Array;
*ArrayPointer = NewArray;
free(GC);
*Array_Length = *Array_Length - 1;
}
/*
This method was designed to place a string into an index.
*/
void Fill( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN], const char * String, int Index)
{
strcpy( Array[Index], String );
}
/*
This method was designed to place fill each string array contained within the array of string arrays with 0's.
*/
void PrepareFileAndPathArrays( char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LEN], int ROWS )
{
size_t Size;
Size = sizeof( *FullPathNames ) * ROWS;
memset(FullPathNames, 0, Size);
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a two-dimensional array of fixed length in C,
How can I allocate memory for it, so I will be able to use it
out of the function scope? (When trying to use malloc/calloc the compiler
says you cant convert void* / char** to char[FIXED][FIXED])
[update from comment:]
So I'll just say what I'm trying to do:
A function I wrote should return a list (implemented as a struct) of 2D arrays it creates, but as they are creates as local variables they 'die' and can't be returned / reached afterwards
You can allocate dynamic memory for an array with C VLAs (char ** is the wrong type though):
int nrows, ncols;
char (*array)[ncols] = malloc(ncols * nrows);
As you've noticed, arrays are not pointers.
In particular, arrays of arrays are not pointers to pointers.
(To see this clearly, draw them on paper.)
However, an array is implicitly converted to a pointer to its first element in certain contexts, such as when being passed as a parameter to or returned from a function.
So, an array of arrays can be converted into a pointer to an array:
int a[3][4];
int (*b)[4] = a; /* b is a pointer to an array of four elements - the first element of a */
And returning one from a function (this one is a mess to read):
int (*make_stuff(size_t size))[4]
{
return malloc(size * sizeof(int[4]));
}
But the whole pointer-to-array syntax is quite messy and unreadable and almost impossible to get right.
I personally find these get more readable if you use a typedef:
typedef int row[4];
row a[3];
row *b = a;
row *c = malloc(3 * sizeof(row));
row* make_stuff(size_t size)
{
return malloc(size * sizeof(row));
}
An array of fixed length is stored in automatic storage i.e., Stack which remains in the function scope. To store the variable in Heap storage, you have to allocate memory for that dynamically using malloc/calloc.
For example( 2D Array )
// N x M array
char **a = malloc( sizeof *a * N ) ;
if( a == NULL )
{
// Error allocating memory
return -1 ;
}
for( i = 0; i < N; i++ )
{
a[i] = malloc( sizeof * a[i] * M ) ;
}
For example( 1D Array ),
void SomeFunc( void )
{
char a[10] ; // will be stored in stack (function scope)
char *b ; // declare a pointer that points to char memory.
b = malloc( 10 * sizeof(char) ) ;
if( b == NULL )
{
// Error in allocating memory
return -1 ;
}
// will be stored in Heap (scope = till you free the memory)
//... Your code goes here...
//... Call to other functions
free( b ) ;
}
Also, you can make it global or static, if you do not want to use malloc/calloc.
Ex:
char a[10] = {0} ; // Global variable, stored in Data segment
void SomeFunc( void )
{
static char b[10] = {0} ; // static variable, stored in Data segment
}
The scope for variables stored in Data segment will be through out the execution. So you can use them, even outside the SomeFunc()
I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.
I want to make a FUNCTION which calculates size of passed array.
I will pass an Array as input and it should return its length. I want a Function
int ArraySize(int * Array /* Or int Array[] */)
{
/* Calculate Length of Array and Return it */
}
void main()
{
int MyArray[8]={1,2,3,0,5};
int length;
length=ArraySize(MyArray);
printf("Size of Array: %d",length);
}
Length should be 5 as it contains 5 elements though it's size is 8
(Even 8 will do but 5 would be excellent)
I tried this:
int ArraySize(int * Array)
{
return (sizeof(Array)/sizeof(int));
}
This won't work as "sizeof(Array)" will retun size of Int Pointer.
This "sizeof" thing works only if you are in same function.
Actually I am back to C after lots of days from C# So I can't remember (and Missing Array.Length())
Regards!
You cannot calculate the size of an array when all you've got is a pointer.
The only way to make this "function-like" is to define a macro:
#define ARRAY_SIZE( array ) ( sizeof( array ) / sizeof( array[0] ) )
This comes with all the usual caveats of macros, of course.
Edit: (The comments below really belong into the answer...)
You cannot determine the number of elements initialized within an array, unless you initialize all elements to an "invalid" value first and doing the counting of "valid" values manually. If your array has been defined as having 8 elements, for the compiler it has 8 elements, no matter whether you initialized only 5 of them.
You cannot determine the size of an array within a function to which that array has been passed as parameter. Not directly, not through a macro, not in any way. You can only determine the size of an array in the scope it has been declared in.
The impossibility of determining the size of the array in a called function can be understood once you realize that sizeof() is a compile-time operator. It might look like a run-time function call, but it isn't: The compiler determines the size of the operands, and inserts them as constants.
In the scope the array is declared, the compiler has the information that it is actually an array, and how many elements it has.
In a function to which the array is passed, all the compiler sees is a pointer. (Consider that the function might be called with many different arrays, and remember that sizeof() is a compile-time operator.
You can switch to C++ and use <vector>. You can define a struct vector plus functions handling that, but it's not really comfortable:
#include <stdlib.h>
typedef struct
{
int * _data;
size_t _size;
} int_vector;
int_vector * create_int_vector( size_t size )
{
int_vector * _vec = malloc( sizeof( int_vector ) );
if ( _vec != NULL )
{
_vec._size = size;
_vec._data = (int *)malloc( size * sizeof( int ) );
}
return _vec;
}
void destroy_int_vector( int_vector * _vec )
{
free( _vec->_data );
free( _vec );
}
int main()
{
int_vector * myVector = create_int_vector( 8 );
if ( myVector != NULL && myVector->_data != NULL )
{
myVector->_data[0] = ...;
destroy_int_vector( myVector );
}
else if ( myVector != NULL )
{
free( myVector );
}
return 0;
}
Bottom line: C arrays are limited. You cannot calculate their length in a sub-function, period. You have to code your way around that limitation, or use a different language (like C++).
You can't do this once the array has decayed to a pointer - you'll always get the pointer size.
What you need to do is either:
use a sentinel value if possible, like NULL for pointers or -1 for positive numbers.
calculate it when it's still an array, and pass that size to any functions.
same as above but using funky macro magic, something like: #define arrSz(a) (sizeof(a)/sizeof(*a)).
create your own abstract data type which maintains the length as an item in a structure, so that you have a way of getting your Array.length().
What you ask for simply can't be done.
At run time, the only information made available to the program about an array is the address of its first element. Even the size of the elements is only inferred from the type context in which the array is used.
In C you can't because array decays into a pointer(to the first element) when passed to a function.
However in C++ you can use Template Argument Deduction to achieve the same.
You need to either pass the length as an additional parameter (like strncpy does) or zero-terminate the array (like strcpy does).
Small variations of these techniques exist, like bundling the length with the pointer in its own class, or using a different marker for the length of the array, but these are basically your only choices.
int getArraySize(void *x)
{
char *p = (char *)x;
char i = 0;
char dynamic_char = 0xfd;
char static_char = 0xcc;
while(1)
{
if(p[i]==dynamic_char || p[i]==static_char)
break;
i++;
}
return i;
}
int _tmain(int argc, _TCHAR* argv[])
{
void *ptr = NULL;
int array[]={1,2,3,4,5,6,7,8,9,0};
char *str;
int totalBytes;
ptr = (char *)malloc(sizeof(int)*3);
str = (char *)malloc(10);
totalBytes = getArraySize(ptr);
printf("ptr = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(int)));
totalBytes = getArraySize(array);
printf("array = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(int)));
totalBytes = getArraySize(str);
printf("str = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(char)));
return 0;
}
Not possible. You need to pass the size of the array from the function, you're calling this function from. When you pass the array to the function, only the starting address is passed not the whole size and when you calculate the size of the array, Compiler doesn't know How much size/memory, this pointer has been allocated by the compiler. So, final call is, you need to pass the array size while you're calling that function.
Is is very late. But I found a workaround for this problem. I know it is not the proper solution but can work if you don't want to traverse a whole array of integers.
checking '\0' will not work here
First, put any character in array at the time of initialization
for(i=0;i<1000;i++)
array[i]='x';
then after passing values check for 'x'
i=0;
while(array[i]!='x')
{
i++;
return i;
}
let me know if it is of any use.
Size of an arry in C is :
int a[]={10,2,22,31,1,2,44,21,5,8};
printf("Size : %d",sizeof(a)/sizeof(int));