Changing pointer address in function - c

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.

Related

Why does this example of pointer dereferencing work?

I have some code, and it works, and I don't understand why. Here:
// This structure keeps the array and its bookkeeping details together.
typedef struct {
void** headOfArray;
size_t numberUsed;
size_t currentSize;
} GrowingArray;
// This function malloc()'s an empty array and returns a struct containing it and its bookkeeping details.
GrowingArray createGrowingArray(int startingSize) { ... }
// Self-explanatory
void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) { ... }
// This function realloc()'s an array, causing it to double in size.
void growGrowingArray(GrowingArray* arrayToGrow) { ... }
int main(int argc, char* argv[]) {
GrowingArray testArray = createGrowingArray(5);
int* testInteger = (int*) malloc(1);
*testInteger = 4;
int* anotherInteger = (int*) malloc(1);
*anotherInteger = 6;
appendToGrowingArray(&testArray, &testInteger);
appendToGrowingArray(&testArray, &anotherInteger);
printf("%llx\n", **(int**)(testArray.headOfArray[1]));
return 0;
}
So far, everything works exactly as I intend. The part that confuses me is this line:
printf("%llx\n", **(int**)(testArray.headOfArray[1]));
By my understanding, the second argument to printf() doesn't make sense. I got to mostly by trial and error. It reads to me as though I'm saying that the second element of the array of pointers in the struct is a pointer to a pointer to an int. It's not. It's just a pointer to an int.
What does make sense to me is this:
*(int*)(testArray.headOfArray[1])
It's my understanding that the second element of the array of pointers contained in the struct will be fetched by the last parenthetical, and that I then cast it as a pointer to an integer and then dereference that pointer.
What's wrong with my understanding? How is the compiler interpreting this?
My best guess is that your appendToGrowingArray looks something like this:
void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) {
growingArray->headOfArray[growingArray->numberUsed++] = itemToAppend;
}
though obviously with additional logic to actually grow the arrow. However the point is that the itemToAppend is stored in the array pointed to by headOfArray.
But, if you look at your appendToGrowingArray calls, you are passing the addresses of testInteger and anotherInteger -- these are already pointers to integers, so you are storing pointers to pointers to integers in your headOfArray when you really intend to store pointers to integers.
So, when you consider testArray.headOfArray[1], it's value is the address on main's stack of the variable anotherInteger. When you dereference it the first time, it now points to the address of the buffer returned by the second malloc call that you stored in anotherInteger. So, it's only when you deference it a second time that you get to the contents of that buffer, namely the number 6.
You probably want to write:
appendToGrowingArray(&testArray, testInteger);
appendToGrowingArray(&testArray, anotherInteger);
instead.
(As noted in a comment, you also should fix your mallocs; you need more than 1 byte to store an integer these days!)

How to return a char** in C

I've been trying for a while now and I can not seem to get this working:
char** fetch (char *lat, char*lon){
char emps[10][50];
//char** array = emps;
int cnt = -1;
while (row = mysql_fetch_row(result))
{
char emp_det[3][20];
char temp_emp[50] = "";
for (int i = 0; i < 4; i++){
strcpy(emp_det[i], row[i]);
}
if ( (strncmp(emp_det[1], lat, 7) == 0) && (strncmp(emp_det[2], lon, 8) == 0) ) {
cnt++;
for (int i = 0; i < 4; i++){
strcat(temp_emp, emp_det[i]);
if(i < 3) {
strcat(temp_emp, " ");
}
}
strcpy(emps[cnt], temp_emp);
}
}
}
mysql_free_result(result);
mysql_close(connection);
return array;
Yes, I know array = emps is commented out, but without it commented, it tells me that the pointer types are incompatible. This, in case I forgot to mention, is in a char** type function and I want it to return emps[10][50] or the next best thing. How can I go about doing that? Thank you!
An array expression of type T [N][M] does not decay to T ** - it decays to type T (*)[M] (pointer to M-element array).
Secondly, you're trying to return the address of an array that's local to the function; once the function exits, the emps array no longer exists, and any pointer to it becomes invalid.
You'd probably be better off passing the target array as a parameter to the function and have the function write to it, rather than creating a new array within the function and returning it. You could dynamically allocate the array, but then you're doing a memory management dance, and the best way to avoid problems with memory management is to avoid doing memory management.
So your function definition would look like
void fetch( char *lat, char *lon, char emps[][50], size_t rows ) { ... }
and your function call would look like
char my_emps[10][50];
...
fetch( &lat, &lon, my_emps, 10 );
What you're attempting won't work, even if you attempt to cast, because you'll be returning the address of a local variable. When the function returns, that variable goes out of scope and the memory it was using is no longer valid. Attempting to dereference that address will result in undefined behavior.
What you need is to use dynamic memory allocation to create the data structure you want to return:
char **emps;
emps = malloc(10 * sizeof(char *));
for (int i=0; i<10; i++) {
emps[i] = malloc(50);
}
....
return emps;
The calling function will need to free the memory created by this function. It also needs to know how many allocations were done so it knows how many times to call free.
If you found a way to cast char emps[10][50]; into a char * or char **
you wouldn't be able to properly map the data (dimensions, etc). multi-dimensional char arrays are not char **. They're just contiguous memory with index calculation. Better fit to a char * BTW
but the biggest problem would be that emps would go out of scope, and the auto memory would be reallocated to some other variable, destroying the data.
There's a way to do it, though, if your dimensions are really fixed:
You can create a function that takes a char[10][50] as an in/out parameter (you cannot return an array, not allowed by the compiler, you could return a struct containing an array, but that wouldn't be efficient)
Example:
void myfunc(char emp[10][50])
{
emp[4][5] = 'a'; // update emp in the function
}
int main()
{
char x[10][50];
myfunc(x);
// ...
}
The main program is responsible of the memory of x which is passed as modifiable to myfunc routine: it is safe and fast (no memory copy)
Good practice: define a type like this typedef char matrix10_50[10][50]; it makes declarations more logical.
The main drawback here is that dimensions are fixed. If you want to use myfunc for another dimension set, you have to copy/paste it or use macros to define both (like a poor man's template).
EDITa fine comment suggests that some compilers support variable array size.
So you could pass dimensions alongside your unconstrained array:
void myfunc(int rows, int cols, char emp[rows][cols])
Tested, works with gcc 4.9 (probably on earlier versions too) only on C code, not C++ and not in .cpp files containing plain C (but still beats cumbersome malloc/free calls)
In order to understand why you can't do that, you need to understand how matrices work in C.
A matrix, let's say your char emps[10][50] is a continuous block of storage capable of storing 10*50=500 chars (imagine an array of 500 elements). When you access emps[i][j], it accesses the element at index 50*i + j in that "array" (pick a piece of paper and a pen to understand why). The problem is that the 50 in that formula is the number of columns in the matrix, which is known at the compile time from the data type itself. When you have a char** the compiler has no way of knowing how to access a random element in the matrix.
A way of building the matrix such that it is a char** is to create an array of pointers to char and then allocate each of those pointers:
char **emps = malloc(10 * sizeof(char*)); // create an array of 10 pointers to char
for (int i = 0; i < 10; i++)
emps[i] = malloc(50 * sizeof(char)); // create 10 arrays of 50 chars each
The point is, you can't convert a matrix to a double pointer in a similar way you convert an array to a pointer.
Another problem: Returning a 2D matrix as 'char**' is only meaningful if the matrix is implemented using an array of pointers, each pointer pointing to an array of characters. As explained previously, a 2D matrix in C is just a flat array of characters. The most you can return is a pointer to the [0][0] entry, a 'char*'. There's a mismatch in the number of indirections.

Returned array in C doesn't contain same values

I'm in the process of teaching myself C and I'm mistified as to what's causing the following issue: when I create an array in a method and return it as a pointer to the calling function, none of the content is correct. I've boiled down this problem to the following example:
char * makeArr(void){
char stuff[4];
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
printf("location of stuff:%p\n",stuff);
int i;
for(i = 0; i < 4; i++){
printf("%c\n",stuff[i]);
}
return stuff;
}
int main(void){
char* myarr;
myarr = makeArr();
int i;
printf("\n");
printf("location of myarr:%p\n", myarr);
for(i = 0; i < 4; i++){
printf("%c\n",myarr[i]);
}
}
The output returns the following:
location of stuff:0028FF08
a
b
c
d
location of myarr:0028FF08
Ä
ÿ
(
(a null character)
So I've verified that the locations between the two values are the same, however the values differ. I imagine that I'm missing some critical C caveat; I could speculate it's something to do with an array decaying into a pointer or a problem with the variable's scope, but and any light that could be shed on this would be much appreciated.
What you're attempting to do is return the address of a local variable, one that goes out of scope when the function exits, no different to:
char *fn(void) {
char xyzzy = '7';
return &xyzzy;
}
That's because, other than certain limited situations, an array will decay into a pointer to the first element of that array.
While you can technically return that pointer (it's not invalid in and of itself), what you can't do is dereference it afterwards with something like:
char *plugh = fn();
putchar (*plugh);
To do so is undefined behaviour, as per C11 6.5.3.2 Address and indirection operators /4 (my bold):
If an invalid value has been assigned to the pointer, the behaviour of the unary * operator is undefined.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
Having stated the problem, there are (at least) two ways to fix it.
First, you can create the array outside of the function (expanding its scope), and pass its address into the function to be populated.
void makeArr (char *stuff) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
int main(void) {
char myarr[4];
makeArr (myarr);
// Use myarr here
}
Second, you can dynamically allocate the array inside the function and pass it back. Items created on the heap do not go out of scope when a function exits, but you should both ensure that the allocation succeeded before trying to use it, and that you free the memory when you're finished with it.
char *makeArr (void) {
char *stuff = malloc (4);
if (stuff != NULL) {
stuff[0]='a';
stuff[1]='b';
stuff[2]='c';
stuff[3]='d';
}
return stuff;
}
int main(void) {
char *myarr;
myarr = makeArr();
if (myarr != NULL) {
// Use myarr here
free (myarr);
}
}
stuff[] only exists on the stack during function call, it gets written over after return. If you want it to hold values declare it static and it will do what you want.
However, the whole idea is fundamentally lame, don't do that in real life. If you want a function to initialize arrays, declare an array outside of the function, pass a pointer to this array as a parameter to the function and then initialize an array via that pointer. You may also want to pass the size of the array as a second parameter.
Since you're learning, a sample code is omitted intentionally.
Your array stuff is defined locally to the function makeArr. You should not expect it to survive past the life of that function.
char * makeArr(void){
char stuff[4];
Instead, try this:
char * makeArr(void){
char *stuff=(char*)calloc(4, sizeof(char));
This dynamically creates an array which will survive until you free() it.

C using malloc and duplicating array

I am supposed to follow the following criteria:
Implement function answer4 (pointer parameter and n):
Prepare an array of student_record using malloc() of n items.
Duplicate the student record from the parameter to the array n
times.
Return the array.
And I came with the code below, but it's obviously not correct. What's the correct way to implement this?
student_record *answer4(student_record* p, unsigned int n)
{
int i;
student_record* q = malloc(sizeof(student_record)*n);
for(i = 0; i < n ; i++){
q[i] = p[i];
}
free(q);
return q;
};
p = malloc(sizeof(student_record)*n);
This is problematic: you're overwriting the p input argument, so you can't reference the data you were handed after that line.
Which means that your inner loop reads initialized data.
This:
return a;
is problematic too - it would return a pointer to a local variable, and that's not good - that pointer becomes invalid as soon as the function returns.
What you need is something like:
student_record* ret = malloc(...);
for (int i=...) {
// copy p[i] to ret[i]
}
return ret;
1) You reassigned p, the array you were suppose to copy, by calling malloc().
2) You can't return the address of a local stack variable (a). Change a to a pointer, malloc it to the size of p, and copy p into. Malloc'd memory is heap memory, and so you can return such an address.
a[] is a local automatic array. Once you return from the function, it is erased from memory, so the calling function can't use the array you returned.
What you probably wanted to do is to malloc a new array (ie, not p), into which you should assign the duplicates and return its values w/o freeing the malloced memory.
Try to use better names, it might help in avoiding the obvious mix-up errors you have in your code.
For instance, start the function with:
student_record * answer4(const student_record *template, size_t n)
{
...
}
It also makes the code clearer. Note that I added const to make it clearer that the first argument is input-only, and made the type of the second one size_t which is good when dealing with "counts" and sizes of things.
The code in this question is evolving quite quickly but at the time of this answer it contains these two lines:
free(q);
return q;
This is guaranteed to be wrong - after the call to free its argument points to invalid memory and anything could happen subsequently upon using the value of q. i.e. you're returning an invalid pointer. Since you're returning q, don't free it yet! It becomes a "caller-owned" variable and it becomes the caller's responsibility to free it.
student_record* answer4(student_record* p, unsigned int n)
{
uint8_t *data, *pos;
size_t size = sizeof(student_record);
data = malloc(size*n);
pos = data;
for(unsigned int i = 0; i < n ; i++, pos=&pos[size])
memcpy(pos,p,size);
return (student_record *)data;
};
You may do like this.
This compiles and, I think, does what you want:
student_record *answer4(const student_record *const p, const unsigned int n)
{
unsigned int i;
student_record *const a = malloc(sizeof(student_record)*n);
for(i = 0; i < n; ++i)
{
a[i] = p[i];
}
return a;
};
Several points:
The existing array is identified as p. You want to copy from it. You probably do not want to free it (to free it is probably the caller's job).
The new array is a. You want to copy to it. The function cannot free it, because the caller will need it. Therefore, the caller must take the responsibility to free it, once the caller has done with it.
The array has n elements, indexed 0 through n-1. The usual way to express the upper bound on the index thus is i < n.
The consts I have added are not required, but well-written code will probably include them.
Altought, there are previous GOOD answers to this question, I couldn't avoid added my own. Since I got pascal programming in Collegue, I am used to do this, in C related programming languages:
void* AnyFunction(int AnyParameter)
{
void* Result = NULL;
DoSomethingWith(Result);
return Result;
}
This, helps me to easy debug, and avoid bugs like the one mention by #ysap, related to pointers.
Something important to remember, is that the question mention to return a SINGLE pointer, this a common caveat, because a pointer, can be used to address a single item, or a consecutive array !!!
This question suggests to use an array as A CONCEPT, with pointers, NOT USING ARRAY SYNTAX.
// returns a single pointer to an array:
student_record* answer4(student_record* student, unsigned int n)
{
// empty result variable for this function:
student_record* Result = NULL;
// the result will allocate a conceptual array, even if it is a single pointer:
student_record* Result = malloc(sizeof(student_record)*n);
// a copy of the destination result, will move for each item
student_record* dest = Result;
int i;
for(i = 0; i < n ; i++){
// copy contents, not address:
*dest = *student;
// move to next item of "Result"
dest++;
}
// the data referenced by "Result", was changed using "dest"
return Result;
} // student_record* answer4(...)
Check that, there is not subscript operator here, because of addressing with pointers.
Please, don't start a pascal v.s. c flame war, this is just a suggestion.

Problem with passing array of pointers to struct among functions in C

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.

Resources