As far as I've understood this far array[1] and array+1 are practically two ways of writing the same thing. However I've been looking at void pointers and arrays recently and made this program to test my understanding of it.
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data) = 5;
*((int*)(data+1)) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)(data+1)));
free(data);
return 0;
}
That is the version of the program that works, for some reason however this version doesn't
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data[0]) = 5;
*((int*)data[1]) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)data1]));
free(data);
return 0;
}
I'm not exactly getting compiler errors but program simply stops running, I've compiled this on a win 10 machine using gcc with the following flags -pedantic-errors -Wall and like i said before, the program compiles but when run I get the classic Program.exe has stopped working error message and so far I really can't think of a single reason why one of those would work and the other wouldn't.
data+1 is not valid C. You cannot do pointer arithmetic on void pointers, since that wouldn't make any sense.
So it would seem that you are using gcc in non-standard crap mode (default setting), which translates void pointer arithmetic to character arithmetic and therefore the program compiles, but as non-standard C. data+1 would then mean +1 byte, not +1 int.
Use gcc as a a standard C compiler instead -std=c11 -pedantic-errors. Then change the code to (int*)data+1.
Also the void** makes no sense, should be a void*. Please note that (int*)data[0] means "do pointer arithmetic on void** type, then cast the result to int*. This is an operator precedence bug. [] has higher precedence than the cast () operator.
Just toss that whole code out and use this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
void* data;
data = malloc( sizeof(int[2]) );
((int*)data)[0] = 5;
((int*)data)[1] = 10;
printf("%d\n", *(int*)data );
printf("%d\n", *((int*)data+1) );
free(data);
return 0;
}
Both your examples are not correct.
void** data = malloc(sizeof(int)*2);
is allocating 2 int integers, but data if of type void**.If you wish to still use this, which is not recommended, you need to allocate 2 void* pointers. This would then be:
void** data = malloc(sizeof(void*)*2);
Having said this, using void** is not needed here. You can just use void* as pointed out in #Lundin's post. Your code would be optimal if you use int *data instead though, as it doesn't really make sense to use void* pointers here. If you decide to do this, your code can just be:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *data;
data = malloc(sizeof(int)*2);
data[0] = 5;
data[1] = 10;
printf("%d\n", data[0]);
printf("%d\n", data[1]);
free(data);
return 0;
}
Which is more straightforward, and skips the complications that void* pointers bring in code.
Note: You must check return of malloc() always, as it can return NULL on failure.
first: please change the type of data to int* or at least to void*.
don't mess with void** unless you need to pass to a function a pointer.
second: change data[0/1] to &data[0/1].data[] is an argument and &data[] is his pointer. if you still using the void* choose *((int*)data+?). if yopu changed to int* use data[?].
third: why to use pointers in this function? this is not a function that need pointers.
fourth: i would suggest in this case to use an array instead of the pointers. if you already know the type and size of your argument so you better use arrays. more comfortable.
Related
It seems there are many questions of the form "should I declare X?" but not this specific one. I hope it is ok to ask this.
The title says it all: why should I declare a pointer? Even better: there are risks if I do not declare the pointer? Consider the following examples:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <string.h>
void func(int *ptr);
int main (int argc, char **argv)
{
int a;
int *PTRa;
a = -1;
PTRa = &a;
func(PTRa);
printf("%d\n", a);
return 0;
}
void func(int *ptr)
{
*ptr = 1;
return;
}
I get a=1. In this case I would say the pointer is declared (and assigned as well): I have the line int *PTRa; (declaration) and the line PTRa = &a; (assignment). The results is correct. I don't get any warning.
Imagine now to replace the main with the following:
int main (int argc, char **argv)
{
int a;
a = -1;
func(&a);
printf("%d\n", a);
return 0;
}
Here I do not declare the pointer but just give the address of a to func. The result is correct and I don't get warnings.
My understanding is that the two approaches are identical: func always gets the same input, the address of a. I would even dare to say that I feel the second approach to be better, as I feel it to be clearer and I feel the variable PTRa to be useless and somewhat redundant. However, I always see codes where the first approach is used and I have the feeling I will be told to do so. Why?
You are correct: there's no point in declaring a pointer in your example. A pointer is just a variable that holds an address. The cleaner approach is to pass directly the address of the variable: func(&a) instead of doing one extra step and declaring PTRa.
Note that not all cases are this simple. For example, if you want to have an array of ints, but you want to be able to grow that array dynamically because you don't know how big it should be you have to declare a pointer:
int count = ...; // get the count from the user, from a file, etc
int *list_of_ints = malloc(sizeof(int) * count);
if (list_of_ints == NULL)
{
// malloc failed.
printf("Not enough memory!\n");
exit(1);
}
// Now `list_of_ints` has enough space to store exactly `count` `int`s
EDIT: as #paulsm4 pointed out in a comment, the question Why use pointers? is a great source of information related to this topic.
EDIT 2: one good reason to want a pointer to the address of a variable might be that you want a pointer inside a structure or array:
struct foo
{
int x;
};
struct bar
{
int y;
struct foo f;
};
struct bar b;
struct foo *ptr_foo = &b.f;
You can now work more easily with b.f because you're just working with a struct foo.
In this case there's no benefit in creating a separate pointer variable.
It might be necessary in more complex cases, just like it's sometimes necessary to create variables of any other type.
From the title, I thought you're talking about pointer type, but actually, you are asking if declaring a variable is needed.
Variable is a piece of memory, storing some numbers(bytes), and the type of the variable, indicating how you and your program interpret those bytes: integer? float? character? etc.
Pointer is the memory address, it could be of a variable, or a function, or something else.
A variable of pointer is a small area in the memory, storing the address of other(or even same) memory.
You decide if you need an extra variable to store the pointer. It's the same to the decision that if you want a variable to store an integer:
int v = -1;
abs(v); // use variable
abs(-1); // use constant
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting. So according to me answer should be option A. But in official GATE-2017 exam answer key, answer is given D. So am i wrong ? how ?
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int *assignval(int *x, int val){
*x = val;
return x;
}
void main(){
clrscr();
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
x = (int *)malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,10);
}
printf("%d\n",*x);
free(x);
getch();
}
(A) compiler error as the return of malloc is not typecast
appropriately.
(B) compiler error because the comparison should be made as x==NULL
and not as shown.
(C) compiles successfully but execution may result in dangling
pointer.
(D) compiles successfully but execution may result in memory leak.
In my opinion option D is only correct when int *x = (int *)malloc(sizeof(int)); is used.
There's no right answer among the choices offered.
The immediately obvious problems with the code, under assumption that the code is supposed to be written in standard C:
Standard library does not have <conio.h> header or <iostream.h> header.
void main() is illegal. Should be int main(). Even better int main(void)
clrscr(), getch() - standard library knows no such functions.
The second malloc leaks memory allocated by the first one (assuming the first one succeeds).
Result of second malloc is explicitly cast - bad and unnecessary practice.
The statement :
int *x = malloc(sizeof(int));
will not lead to compile error, as it declares x as a pointer to int and initializes it right afterwards. It did not have type void beforehand.
The statement :
x = (int *)malloc(sizeof(int));
causes a possible memory leak, as it reallocates the memory which is already allocated for x.
NOTE : However none of this answers is completely correct. This code will not compile for various reasons.
If this is your code, change :
void main()
to :
int main(void)
and also see why you should not cast the result of malloc.
Apart from that, clrscr(), getch(), <conio.h> and <iostream.h> are not recognized by standard library.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting.
There's more than a little debate about whether or not to cast malloc, but it's a stylistic thing. void * is safely promoted to any other pointer.
ISO C 6.3.2.3 says...
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Whatever you choose, pick one and stick with it.
The memory leak is here:
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
// Memory leak
x = (int *)malloc(sizeof(int));
The first malloc points x at allocated memory. The second malloc can only happen if the first succeeded (if x is true). The pointer to the memory allocated by the first malloc is lost.
Using a new variable would fix the leak, keeping in mind that the code is nonsense.
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
int *y = malloc(sizeof(int));
if(NULL==y) return;
y = assignval(y,10);
free(y);
}
As a side note, void main() is technically not a violation of the ISO C standard, it is "some other implementation-defined manner".
5.1.2.2.1 says:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char argv[]) { / ... */ }
or equivalent;) or in some other implementation-defined manner.
I'm guessing you're using a Windows compiler, that would be the "some other implementation". clang considers it an error.
test.c:8:1: error: 'main' must return 'int'
void main(){
^~~~
int
1 error generated.
you should never forget that a void * pointer can be assigned to all type of pointers. in IDEs like visual studio, you get a compile error if you do not perform casting while assigning a void * to <>. for example:
float *ptr = malloc(sizeof(float));//compile error in visual studio.
but if you compile it with GCC without typecasting, you won't get a compile error.
I'm working on a display interface with C. Here is the simplified code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define A_BITMAP {1,2,3}
void getA(int **a){
a[0]=(int*)malloc(12);
memcpy(a[0],(int[])A_BITMAP,12);
}
void main(){
int* a;
getA(&a);
printf("%d",a[2]);
free(a);
}
A_BITMAP is one picture's bitmap array, and I cannot modify its code. Here is my question:
Is there any way not using memcpy() to assign to the malloc(ed) area with macro A_BITMAP?
Will (int[])A_BITMAP generate a large local array on stack? The picture's size is about 2M, is it safe to do so?
You can cast it like that. However, casting should be avoided as it's basically telling the compiler you know better than it and disabling any sanity checks it can do. Also, as apparently you don't really know that A_BITMAP is going to be 3 ints, you're opening yourself up to a whole load of pain by hard coding the size.
Moreover, as pointed out by Sunny, it'll likely copy the array onto the stack when written like that (this depends on your compiler, but it's not something I'd like to risk). You really don't want a 2Mb array on the stack, trust me.
A couple of other points:
a isn't an array, it's a pointer so use *a, not a[0], as it's confusing to the reader
you don't return a result from main which means your program
exits with an error.
You might want to consider something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define A_BITMAP {1,2,3}
void getA(int **a) {
static int data[] = A_BITMAP;
*a = malloc(sizeof(data));
memcpy(*a, data, sizeof(data));
}
int main(){
int* a;
getA(&a);
printf("%d\n", a[2]);
free(a);
return 0;
}
It will create the array on the stack each time the function is called.
It will be better if you declare A_BITMAP as a global array as it will not be allocated on stack.
I'm basically curious if you could do something like this, without the use of pointers:
int myVariable = 0;
int varPointer = &myVariable;
*varPointer += 1; //This obviously won't work, but explains the concept
Yes, I know you can do this with pointers. I want to know if it can be done without pointers.
EDIT>
I want to be able to refer to an address contained in a variable without pointers.
The question is basically, "Can you achieve pointer functionality without using actual pointers? If so, how?"
This code uses integer arithmetic instead of pointer arithmetic:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
int myVariable = 0;
uintptr_t varPointer = (uintptr_t)&myVariable;
varPointer += sizeof myVariable;
return 0;
}
You say in comments:
pointers /can/ contain addresses, but do not necessarily.
Pointer variables must either be null pointers or contain the address of an object. If your code appears to do otherwise then your program has already caused undefined behaviour.
"Hex" has nothing to do with it; base 16 is a way of outputting numbers and you can use any base you like.
Bear in mind that pointers do not necessarily correspond to numbers. On platforms where they don't, then uintptr_t will not exist.
#include <stdio.h>
#include <stdint.h>
int main(void){
int myVariable = 0;
intptr_t varPointer = (intptr_t)&myVariable;
*(int*)varPointer += 1;
printf("%d\n", myVariable);
return 0;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pointer arithmetic in C for getting a string
I am a newbie in C and I would like to get the elements of an array with a function, I have tried different options, but I still do not get the elements.
My function is:
void getelements(int *a, int cl)
{
int *p;
for (p=&a[0];p<&a[cl];p++)
{
printf("%d\n",*p);
}
}
I know that the solution should work like that, but it only prints the first element and then memory positions. I am calling my function with:
int v={10,12,20,34,45};
getelements(&v,5);
Any help? I need to use arithmetic of pointers.
Thanks
First, Please don't update code to fix bugs while a question is open. It makes most of the current answers meaningless, doesn't grant credit where it is due to the person(s) that solved one or more issues in your prior code, and makes the casual reader looking for a related problem to their own completely confused by both the question and the answers therein. If you want to amend an update do so in addition to the original problem, but if it an entirely different issue, then mark as answered, give credit where it is due, and open a new question with your new code and different problem(s) (ideally, anyway).
As written now, your function is fine. But your real issue is this:
// compile with -Wall -Werror and look at the warning here
int v={10,12,20,34,45}; // <== WRONG
getelements(&v,5); // <== Harmless, but bad form.
This should be like this instead, assuming you want to print all elements in the array:
int v[] = {10,12,20,34,45};
getelements(v, sizeof(v)/sizeof(v[0]));
Note the [] following your array. Without it, the &v was masking what would have been a big-fat warning or error from the compiler that int is being passed as an int *. Furthermore, if you compile your prior code with full warnings treated as errors (-Wall -Werror for gcc) you will get an error like the following on your v declaration line:
main.c:116:15: Excess elements in scalar initializer
In other words, everything past the first element was ignored, and thus your pointer was running off into undefined behavior land. Changing the declaration and invocation to what I have above will address this as well as ensure you don't make that mistake again, since sizeof(v[0]) won't even compile unless v is an array or pointer type. The latter can still cause headaches when you use a pointer rather than an array with such a calculation, but thats something you just have to discipline yourself against doing in C.
try this and let me know if that works.
void getelements(int *a)
{
int *p;
int l=5;
for (p=a;p<a+l;p++)
{
printf("%d\n",*p);
}
}
It's best to pass in the length of the array along with the array itself.
#include <stdlib.h>
#include <stdio.h>
void get_elements(int* values, int length)
{
int i;
for (i = 0; i < length; ++i)
{
printf("%d\n", values[i]);
}
}
int main(int argc, char** argv)
{
int vals[3];
vals[0] = 0;
vals[1] = 1;
vals[2] = 2;
get_elements(vals, 3);
getchar();
return 0;
}
Using the code similar to your original post (before the addition of the array length as a method parameter), you could do the follow (which is a bit convoluted if you ask me).
void get_elements(int* values, int length)
{
int *p;
for (p = &values[0]; p < &values[length]; p++)
{
printf("%d\n", *p);
}
}
Actually you are passing array address in
getelements(&v,5)
in function
getelements()
you are treating it like an array!!!
void getelements(int *a, int cl)
{
int *p;
for (p=a;p<a+cl;p++)
{
printf("%d\n",*p);
}
}
Let me know if you are cleared conceptually!!!
As per my knowledge and seeing your code.you have hardcoded the length of array to 5. I think you can also pass array length as a parameter to function; or you can use this function and see if it gives the desired result
void getelements(int *a)
{
int *p;
int i = 0;
int l=5;
p = a
for (i = 0;i<l;i++)
{
printf("%d\n",*(p + i));
}
}