A function I need to use requires a vector argument for return storage with the following signature:
char ***vvar
What am I supposed to pass in there?
How do I access elements afterward?
Let's say you want a function that creates a vector of strings. You might define it and call it like this:
#include "stdio.h"
#include "stdlib.h"
void make_vector(char*** vvar)
{
/* We're going to create a vector of strings. */
char** vector = malloc(sizeof(char*) * 3 );
vector[0] = "Hello";
vector[1] = "world!";
vector[2] = NULL;
/* Now we give the address of our vector to the caller. */
*vvar = vector;
}
int main(void)
{
char** vector_of_strings = NULL;
make_vector(&vector_of_strings);
printf("%s\n", vector_of_strings[0]);
return 0; /* Memory leak is an exercise for the reader. :-) */
}
(In this example it would be simpler to have make_vector return the array, but in a more complex example it's reasonable to pass the address of vector_of_strings.)
I will assume that the vector will contain strings, as that makes the most sense with the signature you describe.
As you also did not give any code, I will assume the function you need to call looks similar to this:
/* This function creates a vector with room for 'length' strings and places it in 'vvar' */
void create_string_vector(int /* in */ length, char*** /* out */ vvar);
As the function expects to be able to change vvar and have that change reflected in the caller, you must pass the address of some variable, so the call should look like
create_string_vector(my_length, &my_var);
That takes care of one level of pointers.
This leaves just the question of how to declare my_var. As it will be a vector, or array, of unknown size, you need to declare it as a pointer. And a string is also a kind of array of unknown size of characters, so you need a pointer for that as well. This leads to the declaration
char* *my_var;
Element access is the easy part: You can treat my_var just as an array:
my_var[0] = "Hello";
This is not a vector by the looks of it.
If the function signature is somethings like function(...,char ***vvar,...), then your solution is not simple.
You need to know how much buffer space you need in each dimension, then create the complicated array as follows:
int dim_1 = 5, dim_2 = 4, dim_3 = 10;
char ***buffer = malloc(sizeof(char**)*dim_1);
for (int i=0;i++;i<dim_1) {
char **buffer_2 = malloc(sizeof(char*)*dim_2);
for (int j=0;j++;j<dim_2) {
char *buffer_3 = malloc(dim_3);
buffer_2[j] = buffer_3;
}
buffer[i] = buffer_2;
}
Related
This probably has been asked already, but I'm unable to find anything on it.
I have a string array, where the numbers of strings in it is determined at runtime (the max string length is known, if that helps). Since I need global access to that array, I used a pointer and malloc'ed enough space to it when I actually know how much has to fit in there:
char *global_strings;
void some_func(int strings_nr, int strings_size)
{
global_strings = (char*) malloc(strings_nr* strings_size* sizeof(char));
}
What would be the correct way in C to use this pointer like a two-dimensional char array equivalent to
global_strings[strings_nr][strings_size] ?
As a global pointer to 2D data, whose N*M characteristics defined at run-time, I'd recommend a helper function to access the strings rather than directly use it. Make it inline or as a macro if desired.
char *global_strings = NULL;
size_t global_strings_nr = 0;
size_t global_strings_size = 0;
// Allocation -
// OK to call again, but prior data may not be organized well with a new string_size
// More code needed to handle that.
void some_func(int strings_nr, int strings_size) {
global_strings_nr = strings_nr; // save for later use
global_strings_size = strings_size; // save for later use
global_strings = realloc(global_strings,
sizeof *global_strings * strings_nr * strings_size);
if (global_strings == NULL) {
global_strings_nr = global_strings_size = 0;
}
}
// Access function
char *global_strings_get(size_t index) {
if (index >= global_strings_nr) {
return NULL;
}
return global_strings + index*global_strings_size;
}
#define GLOBAL_STRINGS_GET_WO_CHECK(index) \
(global_strings + (index)*global_strings_size)
Better to use size_t for array indexing and sizing than int.
Casts not needed.
Memory calculations should begin with a size_t rather than int * int * size_t.
I need to store an array of point (x,y). I read the points from a file, and the number of points are not constant, but i can get it at the first line of the file. So i write a procedure load() to loading the points from the file and store them in a global array. It doesn't work.
My code:
int *array[][]; // this is a pointer to a 2-dimensional array??
void load(){
..
int tempArray[2][n]; //n is the first line of the file
..
array = tempArray;
}
You're trying to return a pointer to memory that is local to the function that defines the variable. Once that function stops running ("goes out of scope"), that memory is re-used for something else, so it's illegal to try and reference it later.
You should look into dynamic allocation, and have the loading function allocate the needed memory and return it.
The function prototype could be:
int * read_points(const char *filename, size_t *num_points);
Where filename is of course the name of the file to open, num_points is set to the number of points found, and the returned value is a pointer to an array holding x and y values, interleaved. So this would print the coordinates of the first point loaded:
size_t num_points;
int *points;
if((points = load_points("my_points.txt", &num_points)) != NULL)
{
if(num_points > 0)
printf("the first point is (%d,%d)\n", points[0], points[1]);
free(points);
}
This declaration of yours does not work:
int *array[][]; // this is a pointer to a 2-dimensional array??
First, it is trying to declare a 2D array of int *. Second, when you declare or define an array, all dimensions except the first must be specified (sized).
int (*array)[][2]; // This is a pointer to a 2D array of unknown size
This could now be used in a major variant of your function. It's a variant because I misread your question at first.
void load(void)
{
...
int tempArray[n][2]; // Note the reversed order of dimensions!
...
array = &tempArray;
...there must be some code here calling functions that use array...
array = 0;
}
Note that the assignment requires the & on the array name. In the other functions, you'd need to write:
n = (*array)[i][j];
Note, too, that assigning the address of a local array to a global variable is dangerous. Once the function load() returns, the storage space for tempArray is no longer valid. Hence, the only safe way to make the assignment is to then call functions that reference the global variable, and then to reset the global before exiting the function. (Or, at least, recognize that the value is invalid. But setting it to zero - a null pointer - will more nearly ensure that the program crashes, rather than just accessing random memory.
Alternatively, you need to get into dynamic memory allocation for the array.
Your question actually is wanting to make a global pointer to a VLA, variable-length array, where the variable dimension is not the first:
int tempArray[2][n]; // Note the reversed order of dimensions!
You simply can't create a global pointer to such an array.
So, there are multiple problems:
Notation for pointers to arrays
Initializing pointers to arrays
Assigning global pointers to local variables
You can't have global pointers to multi-dimensional VLAs where the variable lengths are not in the first dimension.
You should minimize the use of globals.
A more elegant version might go like this:
typedef struct point_ { int x; int y; } point;
point * create_array(size_t n)
{
return calloc(n, sizeof(point));
}
void free_array(point * p)
{
free(p);
}
int main()
{
size_t len = read_number_from_file();
point * data = create_array(len);
if (!data) { panic_and_die(); }
for (size_t i = 0; i != len; ++i)
{
/* manipulate data[i].x and data[i].y */
}
free_array(data);
data = 0; /* some people like to do this */
}
You are trying to assign an array but in C arrays cannot be assigned.
Use memcpy to copy one array to another array. Arrays elements in C are guaranteed to be contiguous.
int bla[N][M] = {0};
int blop[N][M];
/* Copy bla array to blop */
memcpy(blop, bla, sizeof blop);
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));
What do I need to change here so that animal contains {3,4}?
void funct(unsigned char *elf)
{
unsigned char fish[2]={3,4};
elf=fish;
}
int main()
{
unsigned char animal[2]={1,2};
funct(animal);
return 0;
}
EDIT: I see memcpy is an option. Is there another way just manipulating pointers?
Is there another way just manipulating pointers?
No, because animal is not a pointer. animal is an array. When you pass it as an argument to the function, it decays to a pointer to its first element, just as if you had said &animal[0].
Even if you use a pointer and take a pointer to it in funct, it still won't work:
void funct(unsigned char** elf)
{
unsigned char fish[2] = { 3, 4 };
*elf = fish; // oh no!
}
int main()
{
unsigned char animal[2] = { 1, 2 };
unsigned char* animal_ptr = animal;
funct(&animal_ptr);
}
After the line marked "oh no!" the fish array ceases to exist; it goes away when funct returns because it is a local variable. You would have to make it static or allocate it dynamically on order for it to still exist after the function returns.
Even so, it's still not the same as what you want because it doesn't ever modify animal; it only modifies where animal_ptr points to.
If you have two arrays and you want to copy the contents of one array into the other, you need to use memcpy (or roll your own memcpy-like function that copies array elements in a loop or in sequence or however).
Since animal decays to a pointer when passed to a function, you can replace:
elf=fish;
with:
elf[0] = fish[0]; // or: *elf++ = fish[0]
elf[1] = fish[1]; // *elf = fish[1]
or, assuming they're the same size:
memcpy (elf, fish, sizeof (fish));
Post question edit:
EDIT: I see memcpy is an option. Is there another way just manipulating pointers?
There is no safe way to do this by manipulating the pointers if you mean changing the value of the pointer itself. If you pass in a pointer to a pointer, you can change it so that it points elsewhere but, if you point it at the fish array, you're going to get into trouble since that goes out of scope when you exit from funct().
You can use the pointer to transfer characters as per my first solution above (elf[n] array access is equivalent to *(elf+n) pointer access).
One option is to assign the elements individually:
void funct(unsigned char *elf){
elf[0] = 3;
elf[1] = 4;
}
Another option is to use memcpy (which requires including string.h):
void funct(unsigned char *elf){
unsigned char fish[2]={3,4};
memcpy(elf, fish, 2);
}
memcpy takes as parameters the destination, the source, and then the number of bytes to copy, in this case 2.
void funct(unsigned char *elf) {
unsigned char fish[2]={3,4}; // stack variable, will dissapear after the function is exited
// elf=fish; this one assigns to the local copy of elf, that will also dissapear when we return
memcpy(elf, fish, sizeof(fish)); // so we have to copy values
// careful though, because sizeof(fish) can be bigger than sizeof(elf)
}
To help deal with maintenance issues, you're probably better off making a function that returns the pointer you want, and then making sure you've really freed any memory from the original array first.
unsigned char * func()
{
unsigned char * fish = malloc( sizeof(unsigned char) * 2 );
fish[0] = 3;
fish[1] = 4;
return fish;
}
int main ( void )
{
unsigned char * animal = malloc( sizeof(unsigned char) * 2 );
animal[0] = 1;
animal[1] = 2;
free( animal );
animal = func();
}
Trying to reassign an array declared using the 'unsigned char animal[2]' syntax is asking for trouble because it's put the entire original array on the stack, and even if the compiler allowed you to do that, you'd end up with a chunk of unusable memory on the stack. I don't design programming languages, but that feels very wrong.
The Code that follows segfaults on the call to strncpy and I can't see what I am doing wrong. I need another set of eyes to look it this. Essentially I am trying to alloc memory for a struct that is pointed to by an element in a array of pointers to struct.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_POLICY_NAME_SIZE 64
#define POLICY_FILES_TO_BE_PROCESSED "SPFPolicyFilesReceivedOffline\0"
typedef struct TarPolicyPair
{
int AppearanceTime;
char *IndividualFile;
char *FullPolicyFile;
} PolicyPair;
enum {
bwlist = 0,
fzacts,
atksig,
rules,
MaxNumberFileTypes
};
void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
IndividualPolicyPairtoCreate = (PolicyPair *) malloc(sizeof(PolicyPair));
IndividualPolicyPairtoCreate->IndividualFile = (char *)malloc((MAX_POLICY_NAME_SIZE * sizeof(char)));
IndividualPolicyPairtoCreate->FullPolicyFile = (char *)malloc((MAX_POLICY_NAME_SIZE * sizeof(char)));
IndividualPolicyPairtoCreate->AppearanceTime = 0;
memset(IndividualPolicyPairtoCreate->IndividualFile, '\0', (MAX_POLICY_NAME_SIZE * sizeof(char)));
memset(IndividualPolicyPairtoCreate->FullPolicyFile, '\0', (MAX_POLICY_NAME_SIZE * sizeof(char)));
}
void SPFCreateFullPolicyListing(SPFPolicyPair **CurrentPolicyPair, char *PolicyName, char *PolicyRename)
{
int i;
for(i = 0; i < MaxNumberFileTypes; i++)
{
CreateIndividualPolicyListing((CurrentPolicyPair[i]));
// segfaults on this call
strncpy((*CurrentPolicyPair)[i].IndividualFile, POLICY_FILES_TO_BE_PROCESSED, (SPF_POLICY_NAME_SIZE * sizeof(char)));
}
}
int main()
{
SPFPolicyPair *CurrentPolicyPair[MaxNumberFileTypes] = {NULL, NULL, NULL, NULL};
int i;
CreateFullPolicyListing(&CurrentPolicyPair, POLICY_FILES_TO_BE_PROCESSED, POLICY_FILES_TO_BE_PROCESSED);
return 0;
}
Problem is in the prototype of function:
...
void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
...
The function gets a NULL pointer value, sets it to a valid location by malloc but doesn't in any way return it to calling function.
It should be
...
void SPFCreateIndividualPolicyListing(PolicyPair **IndividualPolicyPairtoCreate )
{
*IndividualPolicyPairtoCreate = malloc (...);
...
void SPFCreateIndividualPolicyListing(PolicyPair *IndividualPolicyPairtoCreate )
{
IndividualPolicyPairtoCreate = (PolicyPair *) malloc(sizeof(PolicyPair));
That just assigns to the local IndividualPolicyPairtoCreate variable - C is pass by value, not pass by reference. You're leaking memory, and the caller won't see any changes to the struct you're passing in.
Change that function to e.g. return the newly allocated memory, and instead of
CreateIndividualPolicyListing((CurrentPolicyPair[i]));
Do
CurrentPolicyPair[i] = CreateIndividualPolicyListing();
Because I can't read your code with its excessively long variable and function names, I've rewritten the offending function as follows. So, my first suggestion is: use shorter variable names.
void create_policies(SPFPolicyPair **policies, char *name, char *newname) {
int i;
for(i = 0; i < MaxNumberFileTypes; i++) {
create_policy(policies[i]);
strncpy((*policies)[i].IndividualFile, POLICY_FILES_TO_BE_PROCESSED, SPF_POLICY_NAME_SIZE);
}
}
There are multiple problems with this code.
First, as others have pointed out, create_policy(policies[i]) can not change the value of policies[i] because C is purely pass by value. Write it as
polices[i] = create_policy();
and change create_policy to return the address of policy pair it allocates.
Second, (*policies)[i].IndividualFile is wrong. It should be
(*policies[i]).IndividualFile
or even better
policies[i]->IndividualFile.
Third, you don't use name or newname.
Problem (1) and (2) will both lead to segfaults. Problem (3) indicates either that you've been trying to strip this code down to understand the segfault, or that you're not sure exactly what this function should do.
The rest of this post explains the second bug and its fix in more detail.
You have correctly passed in policies as a pointer to the first element of an array of SPFPolicyPair *s. So, very roughly
policies --> [ ptr0 | ptr1 | ptr2 | ... ]
Each ptri value is a SPFPolicyPair *. There are two ways to interpret such a value: (a) the base of an array of SPFPolicyPair objects, or (b) a pointer to a single such object. The language itself doesn't care which interpretation your using, but in your case, by looking at how you've initialized the policies array, it's clearly case (b).
So, how does the evaluation ((*policies)[i]).IndividualFile go wrong?
*policies returns ptr0 from the diagram above.
That value is now subscripted, as ptr0[i].
The first indication of trouble is that you're only ever using policies[0], and then treating this value, ptr0, as a pointer to the first element of an array of full-sized policy pair objects, eg,
ptr0 -> [ ppair0 | ppair1 | ppair2 | ... ]
This is the array you're indexing. Except that ptr0 does not point to a sequence of policy pair objects, it points to exactly one such object. So, as soon as i is greater than zero, you're off referencing undefined memory.
The revised expression, policies[i]->IndividualFile, works like this:
policies[i] is equivalent to *(policies + i), and returns one of ptr0, ptr1, etc.
ptri->IndividualFile is equivalent to (*ptri).IndividualFile, and returns the base address of the file name for the ith policy pair.