The code snippet below gives the output 11 11 undefined value. But why am I getting the undefined value when the same statement is executed second time ? Is that anything to do with the scope of the function?
void foo(int **const p)
{
int j = 11;
*p = &j;
printf("%d ", **p);
}
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
return 0;
}
When foo() exits, *p points to a variable that is no longer in existence. Therefore you are invoking undefined behaviour.
You are pointing to an item which has been already deallocated as soon as foo function returns. This is an error, then the undefined behaviour happens.
After a variable goes out of scope, it's not automatically overwritten, its value simply remains there until some other instruction uses that memory location to store another value. In the example, the execution of the first printf overwrites the memory location pointed by p, that's why when you read it a second time, you see that its value has changed.
You could fix it as follows:
void foo(int **const p)
{
int *j = (int *)malloc(sizeof(int));
*p = j;
printf("%d ", **p);
}
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
free(p)
return 0;
}
It's not beautiful but for educational purposes it can be good.
Related
I'm learning the pointer in the function. When I pass pointer x into update(), I found that I cannot let it point to another memory? Why does this happen? Why I cannot let the x point to another memory on heap or stack? What should I do if I wanna achieve the goal?
void update(int *x){
int *a;
a=malloc(sizeof(int));
x=a;//x is still point to original a rather than memory
// assigned by malloc()
}
int main() {
int a=4;
int *b =&a;
printf("%d ",*b);
update(b);
printf("%d ",*b);
return 0;
}
Thank you~
You're passing the value of a pointer. If you want to have that pointer modified, then you'll need to pass a pointer to the pointer. Is this what you're intending?
void update(int **x){
int *a;
a = malloc(sizeof(int));
*x = a;
}
int main() {
int a = 4;
int *b = &a;
printf("%d ", b);
update(&b);
printf("%d ", b);
return 0;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
At first code a[0] becomes 31 but in the second one a still 55. Can someone explain me the difference? What is the difference between changing a variable's and array's value in a function?
#include <stdio.h>
int h(int x[]);
int main()
{
printf("Hello, World!\n");
int a[0] = 55;
h(a);
printf("%d", a[0]);
return 0;
}
int h(int x[]) {
x[0] = 31;
}
#include <stdio.h>
int h(int x);
int main()
{
printf("Hello, World!\n");
int a= 55;
h(a);
printf("%d", a);
return 0;
}
int h(int x) {
x = 31;
}
And What about this code? This array is changed. I am really confused.
#include <stdio.h>
int h(int x[], int length);
int main()
{
int i;
int a[]= {5, 5, 5, 5};
h(a, 4);
printf("Array After Function Call\n");
for(i = 0; i < 4; i++) {
printf("%d ", a[i]);
}
return 0;
}
int h(int x[], int length) {
int i;
for(i = 0; i < length; i++) {
x[i] += x[i];
}
printf("Array in Function\n");
for(i = 0; i < length; i++) {
printf("%d ", x[i]);
}
printf("\n");
return 0;
}
And any decent book should have mentioned that arguments to functions are passed by value, meaning the value in the call is copied into the local function argument variable.
Modifying this local variable will only modify the local copy, not the value used in the call to the function.
One can overcome this problem by emulating pass by reference, which is done by passing a pointer to the variable:
void f(int *x)
{
*x = 123; // Dereference the pointer, to set the value of where it's pointing
}
int main(void)
{
int a = 0;
f(&a); // Pass a pointer to the variable a
}
This is really what's happening in the first program you show, you pass a pointer, and modify the value of where the pointer is pointing (the zero-sized array notwithstanding).
It seems that one of your major confusions is about your "array" argument.
When you declare a function as
void f(int a[]);
you don't actually declare an array argument: The compiler will treat it as a pointer and parse it as
void f(int *a);
Another point is that when you use array indexing, like
x[i] += x[i];
you are actually dereferencing the pointer, and write the values to the memory where the pointer is pointing. In fact, for any pointer or array x and index i, the expression x[i] is exactly equal to *(x + i).
#include<stdio.h>
int main()
{
int i = 11;
int *p = &i;
foo(&p);
printf("%d ", *p);
}
void foo(int *const *p)
{ int j = 10;
*p = &j;
printf("%d ", **p);
}
//it showed compile time error. Can anyone please explain
int *const *p
p is a pointer to a constant pointer to int.
You can change p itself;
You cannot change *p;
You can change **p.
void foo(int *const *p)
{ int j = 10;
*p = &j; // nope
printf("%d ", **p);
}
In your code you defined the method after calling it, so you should place it before main()
I have written the following code in C for initializing and increment an array of pointers to int.
#include <stdio.h>
#include <stdlib.h>
int * arr;
void initArray (int *arr, int size) {
arr = malloc(sizeof(int)*size);
for (int i=0; i< size; i++) {
arr[i]= i;
printf("%d ", arr[i]);
}
printf("\n");
}
void incArray(int *arr, int size) {
for (int i=0; i< size; i++) {
arr[i]= i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
void main(){
initArray(arr, 3);
incArray(arr, 3);
}
Unless I use malloc in both functions, the program (when run) gives this error:
Running "/home/ubuntu/workspace/hello-c-world.c"
0 1 2
bash: line 12: 93714 Segmentation fault "$file.o" $args
Process exited with code: 139
Not sure why once the initArray function is called why it needs memory allocation again in increment function. I am assuming it's treating the array for the second function as a separate one whereas I want to increment the values in the first array that initArray function creates.
I'd really appreciate being pointed in the right direction.
You want this:
#include <stdio.h>
#include <stdlib.h>
void initArray (int **arr, int size) {
*arr = malloc(sizeof(int)*size);
for (int i=0; i< size; i++) {
(*arr)[i]= i;
printf("%d ", (*arr)[i]);
}
printf("\n");
}
void incArray(int *arr, int size) {
for (int i=0; i< size; i++) {
arr[i]= i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
void main(){
int *arr;
initArray(&arr, 3); // << this will modify arr
incArray(arr, 3);
}
In your code, you have two variables whose name is arr : one is inside the global scope, and the other one is in initArray function scope. Look at this instruction inside initArray :
arr = malloc(sizeof(int)*size);
As function's local scope is resolved before global's one in C language, it's the arr parameter of the function which is going to store the allocation, not the global arr variable. And as you're returning nothing, this pointer will be destroyed at the end of your function, and you will not have any access to your allocation anymore. And so, the global arr will never be modified and its value will always be NULL or an undefined value.
This is why, inside incArray when you're doing this writing instruction...
arr[i]= i+1;
... you are actually trying to write i + 1 in a NULL or undefined address, which is not an address your processus has the right to write in, causing this segmentation fault.
A simple fix would be to return the pointer in initArray and to store it in your global arr variable, like that:
int * arr;
int* initArray (int size) {
int* arr = malloc(sizeof(int)*size);
// ...
return arr;
}
void incArray(int *arr, int size) {
// ...
}
void main(){
arr = initArray(3);
incArray(arr, 3);
}
The arr in initArray() is hiding the global arr, and modifications made to arr in initArray() are not made to the global arr. Your code then calls incArray() with the (unmodified) global arr — which is still a null pointer. This gives you a seg fault when you try to use it. It also means that you leak the memory when the function returns.
You'll need to work out whether you want the global variable or not — I suggest removing it. Global variables should be avoided when possible.
You will need to change the signature of the initArray() function — there are (at least) two options.
Option 1 — Return pointer to allocated space
You could change initArray() to return a pointer to the allocated space. It would have the signature int *initArray(int size) and you'd call it as:
int *arr = initArray(3);
This yields:
#include <stdio.h>
#include <stdlib.h>
int *initArray(int size)
{
int *arr = malloc(sizeof(int)*size);
if (arr != 0)
{
for (int i = 0; i < size; i++)
{
arr[i] = i;
printf("%d ", arr[i]);
}
printf("\n");
}
return arr;
}
void incArray(int *arr, int size) // Unchanged
{
for (int i = 0; i < size; i++)
{
arr[i] = i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void)
{
int *arr = initArray(3);
if (arr != 0)
incArray(arr, 3);
return 0;
}
Where I compare to 0, you may prefer to compare to NULL. Note that the code is careful to check that allocations succeed before using the allocated space.
Option 2 — Pass a pointer to a pointer
Alternatively, if you like double pointers, you can pass a pointer to a pointer to the function:
void initArray(int **arr, int size)
{
*arr = malloc(sizeof(int) * size);
if (*arr != 0)
{
for (int i = 0; i < size; i++)
{
(*arr)[i] = i;
printf("%d ", (*arr)[i]);
}
printf("\n");
}
}
// incArray unchanged again
int main(void)
{
int *arr;
initArray(&arr, 3);
if (arr != 0)
incArray(arr, 3);
return 0;
}
I am trying to remove the negative numbers from array with the following code. Unfortunately, not getting the results. It just prints the first element over and over. Can someone please let me know where am I going wrong?
#include <stdio.h>
void removenegative(int a[],int *p, int *q);
int main()
{
int a[] = {2, 3, -5, -7, 6, 9};
int i;
int *p, *q;
p = a;
q = a+6-1;
removenegative(a, p,q);
for(i=0;i<6;i++)
{
printf("%2d", *p);
}
printf("\n");
}
void removenegative(int a[],int *p, int *q)
{
int *x;
x= &a[0];
while (p<=q)
{
if (*p>=0)
{
*x = *p;
x++;
}
p++;
}
for( ; x<=q; x++)
{
*x = -1;
}
}
for(i=0;i<6;i++)
{
printf("%2d", *p);
}
You're not changing p!
You are printing only one value:
printf("%2d", *p);
do this before for loop:
p = a;
and add p++ inside loop;
It just prints the first element over and over
Of course it does so...
for(i=0;i<6;i++)
{
printf("%2d", *p);
}
You always print *p, which is a[0]
Change:
printf("%2d", *p);
to:
printf("%2d", a[i]);
You're looping i, but not using it.
Your code is correct:
void removenegative(int a[],int *p, int *q)
{
int *x;
x= &a[0]; // let x point to the first thing in a
while (p<=q) // continue while p points to an address before q
{
if (*p>=0) // if the thing pointed to by p is greater than zero...
{
*x = *p; // copy from p to x, increment x
x++;
}
p++; // increment p
}
for( ; x<=q; x++) // while x is less than q...
{
*x = -1; // fill in -1
}
}
So x is an incrementing write pointer, while p scans the array and q acts as an end-of-array marker.
As I've been beaten to saying while typing this, your output routine is incorrect.