I am passing a multidimensional character array to a function in c. The main() or whatever function determines the size (dimensions) of the input array. I am trying to determine the length and width of the array dynamically in my function. So far, I have been able to determine the width dynamically for the first row. However, if I try to use the same logic to determine the length, I am getting access violation error. This is the code I have so far:
char * myfunc( char* in[] )
{
int index=0, cols=0;
while( in[0][index++] != '\0' );
cols = index - 1;
:
:
}
int main()
{
char *in[3] = {"abcd","efgh","ijkl"};
char *out = myfunc( in );
:
:
}
Luckily for me, 'cols' in all 'rows' of the **in are equal. I understand a more robust approach will be to first determine the number of rows and test the number of cols for each row there after. I am causing an access violation error every time I try to do something similar for the rows.
I should mention, I cannot redefine the function to pass the dimensions of the array. I should also mention, this is not homework or work-work, I came across this problem while brushing my c coding skills. Is there a way to determine the number of rows in the case above without causing an access violation error?
With the data you have, it can't be done. But you could add a sentinel like this:
char *in[4] = {"abcd", "efgh", "ijkl", NULL};
and then look for the sentinel (which is effectively what you're doing to count the columns, by looking for the sentinel '\0' in the first string).
char * myfunc( char* in[] )
{
int rows;
for(rows = 0; in[rows]; ++rows)
;
printf("%d\n", rows);
.....
.....
}
int main()
{
char *in[] = {"abcd",, "efgh","ijkl", NULL};
char *out = myfunc( in );
}
It's worthwhile detecting columns only if all strings are of the same length.
Related
I'm programming in C. I have loaded a 2d array with words. It is called dictionary[][]. I am trying to use strstr to find out how many of the words have a substring in them of "struct". Here is the code. In my function count_matches I try to iterate through dictionary using the strstr function to compare. It always returns null so I never get to ++matchcount. Any ideas why?
Here is the function. inp is "struct" dictionary is the 2d array and n is the number of lines in the array (I.e. how many words are in the array).
int count_matches(char *inp, char dictionary[MAX_LINES][MAX_LEN], int n)
{
int matchcount = 0;
int i;
for (i=0; i < n; ++i)
{
if (strstr(dictionary[i], inp) !=NULL)
{
++matchcount;
}
}
return matchcount;
}
I don't see your problem in the given code snippet.
Think about the following:
Did you mix up MAX_LINES and MAX_LEN?
Is the inp really equal to "struct"?
Did you load the dictionary with at least one word that has the substring "struct"?
Show the code where you make the call to this function if the problem persists.
For example, this works fine:
int main()
{
char dictionary[MAX_LINES][MAX_LEN] = {"hello", "hihello", "bye", "Hello"};
int output = count_matches("hello", dictionary, 4);
printf("%d", output); // Output is 2 as expected
return 0;
}
By the way, you can also consider making the following changes to your code:
MAX_WORDS is more readable than MAX_LINES
You do not necessarily have to write != NULL inside that condition
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);
}
I have an array of names stored in char *namelist[]. When I pass it to a function, I'm unable to display all of the names in the namelist:
int ReadListOfName(const char* names[])
{
//Note: I always get the len = 1
// Anyway I can get total items in names
int len = sizeof(names)/sizeof(char*);
for (i=0; i<len; i++)
printf("%d-%s\n",i,names[i]);
return 0;
}
int main(void)
{
const char* names[] = {"a","b","c"};
ReadListOfName(names);
return 0;
}
What's the problem?
int len = sizeof(names)/sizeof(char*);
This doesn't get you the number of elements, sizeof doesn't do what you want on pointers. You have to pass the length as an additional argument to the function. Also discussed in this C FAQ. You could try:
int ReadListOfName(const char* names[], size_t len)
/* ... */
ReadListOfName(names, sizeof(names)/sizeof(names[0]));
int ReadListOfName(const char* names[])
In this names essentially becomes char ** rather than char * [] as defined your main.
You'll need to pass in another argument to ReadListOfName specifying the length of the array or have a terminating value in your array like argv does. When passed to a function, an array will decay to a pointer; a char*[] will decay to a char**, as you're passing the address of the first element in the array. Therefore your function is in fact interpreted as:
int ReadListOfName(const char **names)
And you're actually equating sizeof(char**)/sizeof(char*), which won't give you the number of elements in the array (it'll probably give you 1).
Add a length argument and then just calculate len before passing it ReadListOfName.
Note that rather than dividing sizeof(names) by sizeof(char*) to get the number of elements in the array, you can instead divide by sizeof(*names), and you wouldn't need to worry about changing char* if you change the type of the elements in names:
int len = sizeof(names)/sizeof(*names);
As the other answers already explain what happens to the array reference when passing it to the function, please find an approach to solve the issue without adding another parameter to the method printing the names.
You might like to add a stopper element to your list like so:
#include <stdio.h>
int ReadListOfName(const char ** names)
{
for (int i=0; names[i]; i++)
printf("%d-%s\n",i,names[i]);
return 0;
}
int main(void)
{
const char* names[] = {"a","b","c", NULL}; /* Please note the additional, last element. */
ReadListOfName(names);
return 0;
}
The essential difference of this approach to the one passing two arguments discribing the list names[], is the fact that its use is less error-prone as the information of the list's size is drawn from the list itself, but from a second independently provided value.
you should pass an additional argument which will explicitly mention the length of the array. and where you are initializing setup some MACRO to fiddle with sizeofs.
sizeof(AnyPointer) gives word size. In case of 32-bit OS, 4 will be returned. similarly 8 will be returned in 64-bit machine.
So sizeof(char*) == sizeof(float*) == sizeof(int*) is true.
If your OS is 32-bit,
sizeof(names) will be 4.
sizeof(char*) also 4.
Obviously you will get len = 1.
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));