I see the following way of initializing a local pointer in almost every part of my code. want to understand the reason and intricacies in doing so.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize_p(char **p)
{
char *p_local = NULL;
p_local=malloc(6);
strcpy(p_local,"sandy");
*p = p_local;
}
int main(void)
{
char *p = NULL;
initialize_p(&p);
printf("Name : %s\n",p);
return 0;
}
It is just that, i am showing here with simple string. And in my actual code, it is being done using structures.
I kind of understand the above logic and also I don't. Please clear the concept involved in the above style of implementing. Also, let me know if there is any other better way of doing the same.
Please Enlighten .. :)
I'd probably return the newly allocated string instead of passing a pointer to a pointer as an argument:
char *initialize(void) {
char *init = "sandy";
char *ret = malloc(sizeof(init)+1);
if (ret != NULL)
strcpy(ret, init);
return ret;
}
int main() {
char *p = initialize();
printf("Name: %s\n", p);
free(p);
return 0;
}
In initialize_p a chunk of memory is allocated and some string is copied into the memory. In order for the caller of initializer to get the address of this new chunk of memory the address of the pointer p is passed to initialize_p:
char **p
+---+---+---+---+---+----+
*p -> | s | a | n | d | y | \0 |
+---+---+---+---+---+----+
if only the *p would have been passed then setting the pointer inside the function would be the equivalent of:
void foo(int a)
{
a=3;
...
}
a better way would be to use strdup which does the same thing as you do in your function
char* initialize_p()
{
return strdup("sandy");
}
also make sure you free the string that is returned to avoid memory leak.
I'd suggest you to create allocation and deallocation function pair
char *createP()
{
char *p = NULL;
p=malloc(6);
strcpy(p,"sandy");
return p;
}
void freeP(char *p)
{
if (p) free(p);
}
int main(void)
{
char *p = createP();
printf("Name : %s\n",p);
freeP(p);
return 0;
}
Clearing the concept? Well, in such a simple case I don't see the point in operating with byref output parameters - for me, object-oriented-like structure constructor functions are easier to understand if they work like this:
struct foo *bar = myobj_new(); // uses malloc and returns a pointer
// do something with bar
myobj_destroy(bar); // uses free
Some agree that this design is good because then the return value of the function can be used as an error/success code (have you seen SQLite3?), but I disagree. I think the primary, the most important result of a function should go through the return value, and not some auxiliary stuff. (I tend to write libraries in which failure is indicated by returning NULL and setting a byref-passed error code).
The only valid scenario I can think of is when it's more logical or symmetrical to pass arguments like this. For example, imagining a very strange sort function which is similar to the C stdlib function qsort(), but requires its comparison function itself to make the swapping of two elements when needed. The comparison function obviously needs byref access to its two parameters in order to exchange them, but it may also be useful to return the originally encountered order to the caller sort function in order to optimize the algorithm. So this comparison function could be something like:
int compare(void *a, void *b)
{
int x = *(int *)a;
int y = *(int *)b;
if (x > y)
{
*(int *)a = y;
*(int *)b = x;
return +1;
} else if (x < x) {
return -1;
}
return 0;
}
Well, pretty much that's it about my opinion...
it's an out-parameter. the function produces a result for you, and saves it to the parameter you pass. this is often used when the size of the result may vary, or if the type of the parameter is Opaque.
Personally, I think returning the result is much clearer, and is less error-prone when a dynamic allocation is required (as seen in JerryCoffin's answer +1).
when a dynamic allocation is not required, then pass it by reference (as a non-const parameter) if it is not trivially small:
struct t_struct { int a[100]; };
void InitStruct(struct t_struct* pStruct) {
pStruct->a[0] = 11;
...
}
struct t_struct s;
void InitStruct(&s);
and if it is trivially small, you may consider returning by value.
Related
I have an assignment in C to implement a abstract data type STACK. The nature of the data type requires key structure that needs to have memory allocated. My problem is that my instructor insists, for now, for the initialization function to take in a pointer to the key structure. The init() function will do nothing more than allocate the memory necessary for the structure and set a field to zero, but the pointer that is passed in needs to be assigned that memory location.
I can't think of a way to do this without either having the function return a pointer, or to pass in a 2-star pointer - both of which are not allowed. I know The function prototype must be (where stackT* is a pointer to the key STACK data structure):
void init(stackT* stack);
I came up with this and it works fine:
void init(stackT** stack){
*stack = (stackT*) malloc(sizeof(stack));
(*stack)->count = 0;
return;
}
But it does not abide by the restrictions of the assignment.
tl;dr version:
Basically, how can I pass in the address of my original pointer to the STACK data structure (&stackPtr) into a function that takes one-star pointers as arguments and not get a pointer-type warning? Further, once you change the arguments to (stackT* stack) the below code does not work, even though I am passing the same thing either way - this is where my problem is.
I thought it is REQUIRED to have the argument as a 2-star pointer if you intend to pass in a pointer to a pointer .. the compiler must know what it is dealing with when you dereference a pointer.
At any rate, I am not sure how to do this given the restrictions. In my opinion this is only making it unnecessarily more difficult.
I believe, as pointed out in a comment, that you're missing the intention.
I think the idea is that the "root" stackT instance should be a well-known structure, so that you can declare one locally. Then you call init() to set up the actual stack described by the stackT instance:
int push_four(void)
{
stackT my_stack;
init(&my_stack);
push(&my_stack, 1);
push(&my_stack, 2);
push(&my_stack, 3);
push(&my_stack, 4);
}
The above assumes that the stack stores integers, i.e. the allocation inside init() should be something like:
void init(stackT *stack)
{
stack->items = malloc(64 * sizeof *items);
stack->count = 0;
}
And this, in turn, assumes a declaration like:
typedef struct {
int *items;
size_t count;
} stackT;
Of course, the default maximum depth (64) should be a parameter to init(), you must check (but not cast!) the return value of malloc(), and so on.
Typically when you have complex structures then there is a control struct and that one will have a pointer to the real memory.
Example:
struct stack_control_s {
void * memory;
size_t memory_size;
size_t current_size;
};
Then you would pass a pointer to the control structure to your initialiser and make it do the real work;
#define STACK_MIN_SIZE 0x100
int stack_init(struct stack_control_s * stack) {
memset(stack, 0, sizeof(*stack));
stack->memory = calloc(STACK_MIN_SIZE, 1);
if (!stack->memory)
return -1; //error
stack->memory_size = STACK_MIN_SIZE;
return 0; // all good
}
Here is a slightly modified header for a generic C list that I once made. I have added to macros to make it useable as a stack. Maybe this will give you some inspirations:
list_t.h
Use:
list_t(char) mylist;
list_init(&mylist);
list_push(&mylist, 'A');
printf("%c\n", list_pop(&mylist));
Probably it is not the best solution, but you can define your stack globally.
In this case it will look like a:
stackT G_stack;
....
void init(stackT* stack){
stack->count = 0;
return;
}
int main() {
.....
init(&G_stack);
.....
}
In this case you don't need to change prototype.
This assignes the pointer the address of the definition of STACK and passes the pointer to be initialized (using a single * :)... Will this work for you?
#include <ansi_c.h>
typedef struct {
int count;
} COUNT;
typedef struct {
COUNT count;
int *element1;
int *element2;
int address;
} STACK;
STACK stack, *pStack;
void InitStack(STACK *iS);
int main(void)
{ //This is how I think you will meet the
//criteria you are talking about (single *)
pStack = &stack; //assigning address of stack to pointer
InitStack(pStack);
//pStack->address == pStack
return 0;
}
void InitStack(STACK *iS)
{
iS->count.count = 0;
iS->address = (int)iS; //assigning address of stack to member of struct
iS->element1 = calloc(10, sizeof(int));
iS->element2 = calloc(10, sizeof(int));
}
I need to pass the address of a pointer to a structure to a function, which inturn will dynamically allocate the memory for an array of structures and fill in the values.
Now from my calling method, once i return from the func1, i should be able to iterate through the array of structure and display the value of the structure variables.
Can someone explain how to pass the address of the pointer to the structure, also iterating through the array of structures created dynamically ?
my sample code looks like this:
struct test {
int a;
int b;
};
void func1(int *n,struct test **testobj)
{
n=5;
*testobj = (struct test*) malloc(n*sizeof(struct test));
for(i=0;i<n;i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
struct test testobj;int n;
func1(&n,&testobj);
for(i=0;i<n;i++)
{
printf("%d %d",(*testobj)[i].a,*testobj)[i].b);
}
free(testobj);
}
In main() define a pointer to a test structure:
struct test *testPtr;
To take the address of that pointer use the & address-of operator:
&testPtr;
This returns the address of the pointer and has type struct test **
You can then pass this into your function func1, which does the correct allocation (although casting malloc() is generally considered bad practice - Do I cast the result of malloc?). Other than that func1() looks good... the line...
*testobj = malloc(n*sizeof(struct test));
... is correct. *testobj dereferences your double pointer that you got by doing &testPtr, and stores the address of the new memory in your pointer. You are also correct when you dereference your double-pointer using (*testobj)[i] because [] has higher precedence than * you needed to (as you've correctly done) surround the dereference with brackets to make sure that happens before you take the index.
Thus, when func1() returns the pointer testPtr should now point to the array of n test structures you allocated and can be accessed using testPtr[i].a etc.
EDIT: Your for loop should become
for(i=0;i<n;i++)
printf("%d %d", testobj[i].a, testobj[i].b);
Your original for loop should have given you compilation errors? In the original code testobj is not a pointer, therefore dereferencing it should not be possible.
So the summary answer is in main() declare testobj as a pointer and then access the array elements as testobj[n] :)
EDIT: As eric has pointed out, remove n=5; from func1(). I think you meant *n=5 perhaps as some kind of debugging step... You probably mean to use n as the input to the function to say how many objects you want in your structure array. Either initialise n or perhaps re-define func1() to be
void func1(int n,struct test **testobj) // n is no longer a poitner, just a number
create your array of pointers to structures in declaration step itself and simply pass it to the function
struct test *testobj[10];
func1(&n,testobj);
This passes the whole array of pointers to the function
It isn't entirely clear which version you're asking for, but one of these should cover it:
/* allocate some number of tests.
*
* out_n: out parameter with array count
* returns: an array of tests
*/
struct test* allocate_some_tests(int *out_n) {
int n = 5; /* hardcoded, random or otherwise unknown to caller */
*out_n = n
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
/* allocate a specific number of tests.
*
* n: in parameter with desired array count
* returns: an array of tests
*/
struct test* allocate_n_tests(int n) {
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
Note that you can just return the allocated array, you don't need a pointer-to-pointer here.
As for calling them, and iterating over the result:
void print_tests(struct test *t, int n) {
for (; n--; t++)
printf("{%d, %d}\n", t->a, t->b);
}
int main()
{
int count1; /* I don't know how many yet */
struct test *array1 = allocate_some_tests(&count1);
print_tests(array1, count1);
int count2 = 3; /* I choose the number */
struct test *array2 = allocate_n_tests(count2);
print_tests(array2, count2);
}
Your code appears pretty much ok to me.
only edit that should make it fine is--
in place of
struct test testobj;
put the following code
struct test *testobj;
and keep the remaining as it is..!
here's the working version of what's required, here the memory is allocated in the called function just as required
#include <stdlib.h>
#include <stdio.h>
struct tests {
int a;
int b;
};
void func1(int *n,struct tests **testobj)
{
int i;
*n=5;
*testobj = (struct tests*) malloc((*n)*sizeof(struct tests));
for(i=0;i<(*n);i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
int i;
struct tests *testobj;int n;
func1(&n,&testobj);
for(i=0;i<(n);i++)
{
printf("%d %d",(testobj)[i].a,testobj[i].b);
}
free(testobj);
}
I've just started to work with C, and never had to deal with pointers in previous languages I used, so I was wondering what method is better if just modifying a string.
pointerstring vs normal.
Also if you want to provide more information about when to use pointers that would be great. I was shocked when I found out that the function "normal" would even modify the string passed, and update in the main function without a return value.
#include <stdio.h>
void pointerstring(char *s);
void normal(char s[]);
int main() {
char string[20];
pointerstring(string);
printf("\nPointer: %s\n",string);
normal(string);
printf("Normal: %s\n",string);
}
void pointerstring(char *s) {
sprintf(s,"Hello");
}
void normal(char s[]) {
sprintf(s,"World");
}
Output:
Pointer: Hello
Normal: World
In a function declaration, char [] and char * are equivalent. Function parameters with outer-level array type are transformed to the equivalent pointer type; this affects calling code and the function body itself.
Because of this, it's better to use the char * syntax as otherwise you could be confused and attempt e.g. to take the sizeof of an outer-level fixed-length array type parameter:
void foo(char s[10]) {
printf("%z\n", sizeof(s)); // prints 4 (or 8), not 10
}
When you pass a parameter declared as a pointer to a function (and the pointer parameter is not declared const), you are explicitly giving the function permission to modify the object or array the pointer points to.
One of the problems in C is that arrays are second-class citizens. In almost all useful circumstances, among them when passing them to a function, arrays decay to pointers (thereby losing their size information).
Therefore, it makes no difference whether you take an array as T* arg or T arg[] — the latter is a mere synonym for the former. Both are pointers to the first character of the string variable defined in main(), so both have access to the original data and can modify it.
Note: C always passes arguments per copy. This is also true in this case. However, when you pass a pointer (or an array decaying to a pointer), what is copied is the address, so that the object referred to is accessible through two different copies of its address.
With pointer Vs Without pointer
1) We can directly pass a local variable reference(address) to the new function to process and update the values, instead of sending the values to the function and returning the values from the function.
With pointers
...
int a = 10;
func(&a);
...
void func(int *x);
{
//do something with the value *x(10)
*x = 5;
}
Without pointers
...
int a = 10;
a = func(a);
...
int func(int x);
{
//do something with the value x(10)
x = 5;
return x;
}
2) Global or static variable has life time scope and local variable has scope only to a function. If we want to create a user defined scope variable means pointer is requried. That means if we want to create a variable which should have scope in some n number of functions means, create a dynamic memory for that variable in first function and pass it to all the function, finally free the memory in nth function.
3) If we want to keep member function also in sturucture along with member variables then we can go for function pointers.
struct data;
struct data
{
int no1, no2, ans;
void (*pfAdd)(struct data*);
void (*pfSub)(struct data*);
void (*pfMul)(struct data*);
void (*pfDiv)(struct data*);
};
void add(struct data* x)
{
x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...
4) Consider a structure data which size s is very big. If we want to send a variable of this structure to another function better to send as reference. Because this will reduce the activation record(in stack) size created for the new function.
With Pointers - It will requires only 4bytes (in 32 bit m/c) or 8 bytes (in 64 bit m/c) in activation record(in stack) of function func
...
struct data a;
func(&a);
...
Without Pointers - It will requires s bytes in activation record(in stack) of function func. Conside the s is sizeof(struct data) which is very big value.
...
struct data a;
func(a);
...
5) We can change a value of a constant variable with pointers.
...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...
in addition to the other answers, my comment about "string"-manipulating functions (string = zero terminated char array): always return the string parameter as a return value.
So you can use the function procedural or functional, like in printf("Dear %s, ", normal(buf));
The function proto type like int xxxx(int) or void xxx(int)
You could use a global variable (or, a little better, you could use a static variable declared at file scope), or you could change your functions to take an output parameter, but ultimately you should just use a return statement, since that's really what it's for.
The two standard ways to return values out of functions in C are to either do it explicitly with the return statement, or to use a pointer parameter and assign into the object at the pointer.
There are other ways, but I'm not going into them for fear of increasing the amount of evil code in the world. You should use one of those two.
Use pass by reference:
void foo(int* x, int* y) {
int temp;
temp = *x;
x* = *y;
y* = temp;
}
void main(void) {
int x = 2, y=4;
foo(&x, &y);
printf("Swapped Nums: %d , %d",x,y);
}
You could have a global variable that you assign the value to.
You could pass an object that stores the integer, and if you change it in the function, it'll change elsewhere too, since objects are not value type.
It also depends on the programming language that you're using.
EDIT: Sorry I didn't see the C tag, so ignore my last statement
Typically you provide a reference to an external variable to your function.
void foo(int *value)
{
*value = 123;
}
int main(void)
{
int my_return_value = 0;
foo(&my_return_value);
printf("Value returned from foo is %d", my_return_value);
return 0;
}
The simple answer is given a prototype like the first one you must use the return statement as the int return value dictates it.
In principle it is possible to do something horrible like cast a pointer to an int and pass it in as a parameter, cast it back and modify it. As others have alluded to you must be sure you understand all the implications of doing this, and judging by your question I'd say you don't.
int wel();
int main()
{
int x;
x = wel();
printf("%d\n",x);
return 0;
}
int wel()
{
register int tvr asm ("ax");
tvr = 77;
}
Compiled with GCC compiler in ubuntu machine. In borland compiler, different way to return.
If you need to return more than one value, why not use a pointer to a new allocated struct?
typedef struct { int a, char b } mystruct;
mystruct * foo()
{
mystruct * s = (mystruct *) malloc(sizeof(mystruct));
return s;
}
Not tested, but should be valid.
Many functions in c take pointer to constant strings/chars as parameters eg void foo(const char *ptr) . However I wish to change the string pointed by it (ptr).how to do it in c
You can just cast away the const:
void evil_function(const char *ptr)
{
char *modifiable = (char *) ptr;
*modifiable = 'f';
}
Note that this is dangerous, consider cases where the data being passed to the function really can't be changed. For instance, evil_function("bar"); might crash since the string literal is often placed in read-only memory.
Don't do it as it will cause your code to behave unpredictably. Basically the string pointed by const char* may be stored in the read-only section of your program's data and if you try to write something there, bad things will happen. Remember that foo can be called as foo("Test"), here you have not allocated memory for "Test" yourself, you just have a pointer to memory which contains the string. This memory may be read-only.
You can copy it to another piece of memory, and modify it there.
If you cast it to non-const, and then modify, chances are good you'll just segfault.
void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
foo(data); /* foo first */
sum += data[k];
}
printf("%d\n", sum);
Because foo() does not change its argument, the compiler can change this code to
void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
sum += data[k]; /* sum first */
foo(data);
}
printf("%d\n", sum);
But, if foo() changes the values in the data array, the results will be different according to the order the compiler chose to code the loop!
In short: don't lie to your compiler
How to lie to the compiler
Cast the const away
void foo(const char *readonly) {
char *writable = (char *)readonly;
/* now lie to the compiler all you like */
}
by notation "const char *ptr" we are telling Compiler
that ptr contains should not be changed.
Just, we can't change it!
The whole reason the const is so to express that the underlying content is not to be modified by this function, so don't change it because that will most likely break some code which is relying on the constness. other then that you can always cast the constness away using either const_cast<char*> or by directly casting the pointer
If you do it like this:
void dont_do_this_at_home(const char *ptr)
{
char **steve-o_ptr = (char **) &ptr;
char *bam_margera = "viva la bam";
*steve-o_ptr = bam_margera;
}
Then the pointer that you send into the function will be changed despite being a const pointer, the other suggestions so far only let you change the contents of the string, not the pointer to the string.
And I agree with the others that you shouldn't, ever, "un-const" any parameter you get, since the callee may really depend on that there are no side-effects to the function regarding those parameters.
There is also this way to get rid of the warnings/errors
typedef struct {
union {
const void* the_const;
void* the_no_const;
} unconsting;
}unconst_t;
/* Here be dragons */
void* unconst_pointer(const void* ptr) {
unconst_t unconst.unconsting.the_const = ptr;
return unconst.unconsting.the_no_const;
}
As you see it is quite possible and popular to actually do this, but you have to know what you are doing or mysterious faults may appear.