Reading a pointer - c

I have a vector
int a[100].
I have read the vector and gave it the values 1,2,3.
Now i want to use a pointer
int *pa=&a[100].
My question is can I read the pointer via scanf and give the vector a[100] some new values?
i have tried doing this:
for(i=0;i<n;i++)
{
scanf("%d",&a[i])
}
for the vector and for the pointer:
for(i=0;i<n;i++)
{
scanf("%d",&pa)
}
This is my main:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a [100],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
printf("%d",a[i]);
}
for(i=0;i<n;i++)
{
scanf("%d",&pa);
}
for(i=0;i<n;i++)
{
printf("%d",pa);
}
return 0;
}
printf("%d",pa) is giving me 999 and the vector a still has the values 1,2,3.

The following code illustrates that pa points to an object and that *pa designates the object.
#include <stdio.h>
int main(void)
{
// Set size of array.
static const int N = 100;
// Define array.
int a[N];
// Initialize array.
for (int i = 0; i < N; ++i)
a[i] = i+1;
// Define a pointer and initialize it to point to element a[0].
int *pa = &a[0];
/* Scan as if "34" were in the input. Observe that we pass pa, not &pa.
&pa is the address of pa. pa is the value of pa. Its value is the
address of a[0].
*/
sscanf("34", "%d", pa);
// Print a[0]. This will be "34".
printf("%d\n", a[0]);
/* Print *pa. Note that we use *pa, which is the object pa points to.
That objects is a[0], so the result is "34".
*/
printf("%d\n", *pa);
/* Change pa to point to a different element. Note that we use "pa =
address" to set the value. This is different from the initialization,
which had "int *pa = value". That is because declarations need the
asterisk to describe the type, but an assignment just needs the name;
it does not need the asterisk.
*/
pa= &a[4];
// Print *pa. Since pa now points to a[4], this will print "5".
printf("%d\n", *pa);
}

Related

How to reassign a array in c?

#include <stdio.h>
#include <stdlib.h>
void reasi(char** a){
char* x[] = {"1","22","333"};
a = x;
}
int main(){
char* a[] = {"bob","alice","tom"};
reasi(a);
for(int i=0; i< 3; i++){
printf("%s\n",a[i]);
}
}
The desired output should be {"1","22","333"}, but it won't work if I assign the value like that. I do know how to change the value of an int or char but don't know how to reassign the value to an array (without dynamically allocating memory). I tried to update each element inside "a" and it works. Thank you.
What you're doing won't work. You're simply creating a local array and then assigning your local parameter a to the beginning of this array (which changes nothing about the a in main). So the real thing isn't modified.
To actually modify this, you can either do a plain for loop:
// NOTE: this assumes array has the same number of elements as x
void reasi(char** a)
{
char* x[] = {"1","22","333"};
for (unsigned i = 0; i < sizeof x / sizeof *x; ++i)
a[i] = x[i];
}
Or use memcpy:
#include <string.h>
// NOTE: this assumes array has the same number of elements as x
void reasi(char** a)
{
char* x[] = {"1","22","333"};
memcpy(a, x, sizeof x);
}
Your array is not a 2D array. By seeing your code I assume you mistaken 1D array for 2D array, hence I will answer according to it
#include <stdio.h>
#include <stdlib.h>
void reasi(char** a){
a[0] = "1";
a[1] = "22";
a[2] = "333";
}
int main()
{
char* a[] = {"bob","alice","tom"};
reasi(a);
for(int i=0; i< 3; i++)
{
printf("%s\n",a[i]);
}
}
This will give you your desired output.
In C an array has a fixed size. You cannot resize it after the fact. If the size always stays the same, you can copy the new array:
#include <stdio.h>
#include <string.h>
void reasi(char const **a) {
char const *x[] = {"1", "22", "333"};
memcpy(a, x, sizeof x);
}
int main() {
char const *a[] = {"bob", "alice", "tom"};
reasi(a);
for (int i = 0; i < 3; i++)
puts(a[i]);
}
If you do want to resize the array, you are going to have to allocate it dynamically with malloc.
Both a and x are each an array of pointers to char. In C, you cannot assign the contents of an array C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) "the array object ... is not an lvalue."
Instead, you must assign each element (pointer) from x to a or use memcpy() to accomplish the same.
Further, hardcoding the contents of x in your function makes little sense. Why? You have just written a function that does nothing but assign the pointers (to String-Literals "1", "22", "333") and is incapable of doing anything else -- useful.
Why not declare x in main() and pass it as a parameter along with a and the number of elements? That way, you can pass any array of pointers to char as x (with at least 3 elements) and reassign the elements to a).
For example:
#include <stdio.h>
void reasi (char **a, char **x, size_t nelem)
{
for (size_t i = 0; i < nelem; i++) {
a[i] = x[i];
}
}
int main() {
char *a[] = {"bob","alice","tom"},
*x[] = {"1","22","333"},
*y[] = {"4","55","666","7777","8888"};
size_t n = sizeof a / sizeof *a;
reasi (a, x, n);
puts ("x->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
reasi (a, y, n);
puts ("\ny->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
reasi (a, y + 2, n);
puts ("\ny+2->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
}
The refactoring above generalizes your reasi() function, making it reusable and a bit more useful than a single use case of "1", "22", "333".
Example Use/Output
Running you get the expected:
$ ./bin/reasi
x->a
1
22
333
y->a
4
55
666
y+2->a
666
7777
8888
Wrapping memcpy() in a function in that case wouldn't buy you any benefit, you could simply call memcpy (a, x, n * sizeof *a); from main() and avoid the function call overhead (which a decent compiler would likely optimize out anyway).
Look things over and let me know if you have further questions.

Array of pointers whose elements point to another array of pointers

What I need very precisely is an array A[10] and each of its element pointing to the respective element of array B[10] whose each element store its index.
Hence, A[1] points to B[1] and B[1] has value of 1.
So, when I call *A[1] or *B[1], I get 1.
I know it can be super easy if the array B[10] is not an array of pointers but of integers but I need this for another purpose.
This is what I did but segmentation fault was offered.
#include <stdio.h>
int main() {
int *A[10];
int *B[10];
for(int i=0; i<10; i++) {
A[i] = B[i];
*B[i] = i;
printf("\n%d %d",*A[i],*B[i]);
}
}
By the way, I am not very proficient in pointers.
Your commented code :
int main() {
int *A[10]; // an array of 10 pointers, each of them pointing nowhere
int *B[10]; // an array of 10 pointers, each of them pointing nowhere
// now each array a and b contain 10 uninitialized pointers,
// they contain ideterminate values and they point nowhere
for(int i=0; i<10; i++) {
A[i] = B[i]; // copy an uninitialized pointer
// this usually works but it's pointless
*B[i] = i; // you assign i to the int pointed by *B[i]
// but as *B[i] points nowhere you end up with a segfault
printf("\n%d %d",*A[i],*B[i]); // you never get here because the previous
// line terminates the program with a segfault,
// but you'd get a segfault here too for
// the same reason
}
}
Your program is basically equivalent to this:
int main() {
int *a; // a is not initialized, it points nowhere
*a = 1; // probably you'll get a segfault here
}
Accessing the thing pointed by a pointer is called dereferencing the pointer. Dereferencing an uninitialized pointer results in undefined behaviour (google that term), most likely you'll get a seg fault.
I'm not sure what you're trying to achieve, but you probably want something like this:
#include <stdio.h>
int main() {
int* A[10];
int B[10];
for (int i = 0; i < 10; i++) {
A[i] = &B[i];
B[i] = i;
printf("%d %d\n", *A[i], B[i]);
}
}

Why I cannot use int arr[2][2] as a parameter?

void setArr(int x[2][2], int a, int b)
{
for (int i = 0; i < a; i++)
for (int j = 0; j < b; j++)
x[i][j] = 0;
}
int main(void)
{
int *arr[2];
for (int i = 0; i < 2; i++) {
arr[i] = malloc(sizeof(int) * 2);
}
setArr(arr, 2, 2);
}
I know this code will not work, but I do not know the reason behind it. Can any one explain to my why, in this case, I cannot use x[2][2] as a parameter to receive arr.
Thanks
I put the code into a visualizer, and the setArr function sets the element of arr into NULL. I know that NULL is 0 in C. But I cannot connect why and how element of arr can be set to NULL.
Can any one explain to my why, in this case, I cannot use x[2][2] as a parameter to receive arr.
Because you are using wildly different types. int *arr[2]; is an array of 2 int*, each of them assigned to an allocated chunk of memory. That's a lookup table or "jagged array" if you will, not a proper 2D array. See Correctly allocating multi-dimensional arrays for details.
Correct code for allocating a 2D array is this:
#include <stdlib.h>
void setArr(int a, int b, int x[a][b])
{
for (int i = 0; i < a; i++)
for (int j = 0; j < b; j++)
x[i][j] = 0;
}
int main(void)
{
int (*arr)[2] = malloc(sizeof(int[2][2]));
setArr(2, 2, arr);
free(arr);
}
Here arr in main is a pointer to the first element of an int[2][2]. The first element of that 2D array is int[2], and a pointer to such an element is int(*)[2].
Function declaration void setArr(int x[2][2], int a, int b) declares setArr as a function that takes as a first parameter an array of 2 arrays each holding 2 integers. Whereas in the main you declare arr (the variable you pass to setArr) as int *arr[2], that is as a pointer to an array of 2 integers.
The solution is to either change your code in main, for example by declaring arr as int arr[2][2] and remove the for loop, or change the setArr so that it takes a pointer to an array of two integers void setArr(int *x[2], int a, int b).
I'm not sure if the latter could cause any problems (gcc -Wall compiles without warnings), but one thing to notice is the difference in memory layout when declaring arr as a pointer to an array of size 2 or declaring it as an array of 2 arrays of size 2. Compiling and executing the following should show you the difference:
int main(void) {
int *arr[2];
for (int i = 0; i < 2; i++) {
arr[i] = malloc(sizeof(int) * 2);
}
printf("The address of arr[0] is %p\n", &arr[0]);
printf("The address of arr[1] is %p\n\n", &arr[1]);
printf("The address of arr[0][0] is %p\n", &arr[0][0]);
printf("The address of arr[0][1] is %p\n", &arr[0][1]);
printf("The address of arr[1][0] is %p\n", &arr[1][0]);
printf("The address of arr[1][1] is %p\n\n", &arr[1][1]);
int arr2[2][2];
printf("The address of arr2[0] is %p\n", &arr2[0]);
printf("The address of arr2[1] is %p\n\n", &arr2[1]);
printf("The address of arr2[0][0] is %p\n", &arr2[0][0]);
printf("The address of arr2[0][1] is %p\n", &arr2[0][1]);
printf("The address of arr2[1][0] is %p\n", &arr2[1][0]);
printf("The address of arr2[1][1] is %p\n", &arr2[1][1]);
// setArr(arr, 2, 2);
}
Running the executable once on my machine I got the following:
The address of arr[0] is 0x7ffe43d226b0
The address of arr[1] is 0x7ffe43d226b8
The address of arr[0][0] is 0xb62010
The address of arr[0][1] is 0xb62014
The address of arr[1][0] is 0xb62030
The address of arr[1][1] is 0xb62034
The address of arr2[0] is 0x7ffe43d226c0
The address of arr2[1] is 0x7ffe43d226c8
The address of arr2[0][0] is 0x7ffe43d226c0
The address of arr2[0][1] is 0x7ffe43d226c4
The address of arr2[1][0] is 0x7ffe43d226c8
The address of arr2[1][1] is 0x7ffe43d226cc
You can see that the when declaring arr as an pointer to an array, the two arrays of two integers are not contiguous, whereas when declaring it as an array of arrays, they are. Moreover, when declaring it as an array of arrays there is no need to dynamically allocate memory (e.g., using malloc).
x[2][2] is just a declaration of a variable; there is no need to declare a var in input of a function; you must declare it before and just use its address:
void setArr(int** x, int a, int b)

pointer arithmetic with pointer to array

I'm trying to do pointer arithmetic with a pointer to array, but I get a wrong value since I can't dereference the pointer properly.
Here is the code:
#include "stdlib.h"
#include "stdio.h"
int main()
{
int a[] = {10, 12, 34};
for (int i = 0; i < 3; ++i)
{
printf("%d", a[i]);
}
printf("\n");
int (*b)[3] = &a;
for (int i = 0; i < 3; ++i)
{
printf("%d", *(b++));
}
printf("\n");
return 0;
}
In the second for I can't get to print the correct value.
It doesn't work even if I write
printf("%d", *b[i]);
I'd like to see how to print correctly using the b++ and the b[i] syntax.
The following should work:
printf("%d\n", *( *b+i ));
// * b + i will give you each consecutive address starting at address of the first element a[0].
// The outer '*' will give you the value at that location.
instead of:
printf("%d", *(b++));
You have declared b to be a pointer to arrays of 3 integers and you have initialized it with address of a.
int (*b)[3] = &a;
In the first loop you will print the first element of a array but then you will move 3*sizeof(int) and trigger undefined behavior trying to print whatever there is.
To print it correctly:
int *b = a;
// int *b = &a[0]; // same thing
// int *b = (int*)&a; // same thing, &a[0] and &a both points to same address,
// though they are of different types: int* and int(*)[3]
// ...so incrementing they directly would be incorrect,
// but we take addresses as int*
for (int i = 0; i < 3; ++i)
{
printf("%d", (*b++));
}
gcc will complain about the formatting in the second for loop: it will tell you format specifies type 'int' but the argument has type 'int *
your assignment of a to b should look like this:
int *b = a

Function with return type array in C

I have the following function in C:
int[] function(int a){
int * var = (int*)malloc(sizeof(int)*tags);
....
}
*var is it a pointer to an array var?
If yes, how can I return the array (var) in the function?
You can't really return an array from a function, but a pointer:
int * function(int a){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
This code below could clarify a bit how array and pointers works.
The function will allocate memory for "tags" int variables, then it will initialize each element with a number and return the memory segment that points to the array.
From the main function we will cycle and print the array element, then we will free the no longer needed memory.
#include <stdio.h>
#include <stdlib.h>
int *function(unsigned int tags) {
int i;
int *var = malloc(sizeof(int)*tags);
for (i=0; i < tags; i++) {
var[i] = i;
}
return var;
}
int main() {
int *x;
int i;
x = function(10);
for (i=0; i < 10; i++) {
printf("TEST: %i\n", x[i]);
}
free(x); x=NULL;
return 0;
}
How about:
int* function(int tags){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
Arrays and pointers to the base element type are (mostly) synonymous in C/C++, so you can return a pointer to the first element of an array and use that as if it was the array itself.
Note, your code has an input parameter a, but using tags to allocate the memory for the array. I assumed in the above code that you wanted to use the input parameter for that purpose
Also, you will have to call free() on the pointer returned by function above, when you are no longer using the array, to avoid memory leaks. malloc above allocates memory enough to hold tags number of ints, so the array is equivalent to int var[tags];
UPDATE: removed cast for malloc's return
In C, functions cannot return array types. For your purposes, you want to return a pointer to int:
int *function(int a)
{
int *var = malloc(sizeof *var * tags); // where is tags defined?
// are you sure you don't mean a here?
...
return var;
}
This will allocate a block of memory large enough to hold tags integer values and assign the address of the first element of that block to var. Note that var is a pointer to int, not a pointer to an array of int. That pointer is what gets returned from the function.
You can use the subscript oprerator on a pointer expression as though it were an array, like so:
int a = ...;
int *arr = function(a);
...
arr[0] = 0;
arr[1] = 1;
...
arr is a pointer expression, not an array expression, so sizeof arr will return the size of the pointer type, not the size of the block of memory that it points to (because of this, you will want to keep track of the number of elements you allocated separately).
In C an array is basically the same type as a pointer to an element of the array.
So char[] is basically char*
Don't forget to keep track of the size of the array, also I noticed that tags seems to be a global variable, most of the time it's a good idea to avoid global variables
Here is some example code:
#include <stdio.h>
#include <stdlib.h>
int* foo(size_t arrSize){
int* arr = (int*) malloc(sizeof(int)*arrSize);
return arr;
}
int main (int argc, char** argv){
printf("Printing array:\n");
int* arr = foo(42);
for(int i=0; i <42; i++){
arr[i]=i;
}
for (int i=0; i < 42; i++){
printf("Element: %d: %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Resources