How do I memset an array using a pointer to that array?
int *A, n;
printf("\n Enter the size of array : ");
scanf("%d",&n);
A = (int*) malloc(sizeof(*A) * n);
int i = 0;
memset(*A,5,n * sizeof(*A));
for(i = 0; i < n; i++)
printf("%d ", A[i]);
The compiler doesn't emit warnings for no reason:
warning: passing argument 1 of 'memset' makes pointer from integer without a cast
expected 'void *' but argument is of type 'int'
This means that you are not passing the right type to the first argument of memset(), which indeed wants a pointer, while you are passing an integer.
Your pointer A is fine as is, dereferencing it (*A) is not needed and is wrong, the correct call is:
memset(A, 5, n * sizeof(*A));
More importantly though, this is not what you want to do! If you think the above sets all the elements of the allocated array to 5 that's not the case. Instead, memset() sets every single byte to 5 (see the manual page). Since an int is more than one byte (usually 4), this will fill your array with the value 0x05050505 (decimal 84215045) instead of 5.
In order to set every element to 5 you'll need a for loop:
int i = 0;
for (i = 0; i < n; i++)
A[i] = 5;
Finally, don't cast the return value of malloc():
A = malloc(sizeof(*A) * n);
Related
How do I edit a value in an array with pointer in C?
int *pointer;
int array[3][1];
I tried this:
int *Pointer
int array[2][2];
Pointer[1][1]= 6;
but when compiling, I get a segmentation fault error. What to do?
Given some array int Array[Rows][Columns], to make a pointer to a specific element Array[r][c] in it, define int *Pointer = &Array[r][c];.
Then you may access that element using *Pointer in an expression, including assigning to *Pointer to assign values to that element. You may also refer to the element as Pointer[0], and you may refer to other elements in the same row as Pointer[y], where y is such that 0 ≤ y+c < Columns, i.e., Pointer[y] remains in the same row of the array.
You may also use Pointer[y] to refer to elements of the array in other rows as long as none of the language lawyers see you doing it. (In other words, this behavior is technically not defined by the C standard, but many compilers allow it.) E.g., after Pointer = &Array[r][c];, Pointer[2*Columns+3] will refer to the element Array[r+2][c+3].
To make a pointer you can use to access elements of the array using two dimensions, define int (*Pointer)[Columns] = &Array[r];.
Then Pointer[x][y] will refer to element Array[r+x][y]. In particularly, after int (*Pointer)[Columns] = &Array[0]; or int (*Pointer)[Columns] = Array;, Pointer[x][y] and Array[x][y] will refer to the same element.
You can access any given element with this syntax: array[x][y].
By the same token, you can assign your pointer to any element with this syntax: p = &array[x][y].
In C, you can often treat arrays and pointers as "equivalent". Here is a good explanation:
https://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c
However, you cannot treat a simple pointer as a 2-d array. Here's a code example:
/*
* Sample output:
*
* array=0x7ffc463d0860
* 1 2 3
* 4 5 6
* 7 8 9
* p=0x7ffc463d0860
* 0x7ffc463d0864:1 0x7ffc463d0868:2 0x7ffc463d086c:3
* 0x7ffc463d0870:4 0x7ffc463d0874:5 0x7ffc463d0878:6
* 0x7ffc463d087c:7 0x7ffc463d0880:8 0x7ffc463d0884:9
*/
#include <stdio.h>
int main()
{
int i, j, *p;
int array[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
// Dereference 2-D array using indexes
printf("array=%p\n", array);
for (i=0; i < 3; i++) {
for (j=0; j < 3; j++)
printf ("%d ", array[i][j]);
printf ("\n");
}
// Dereference 2-D array using pointer
p = &array[0][0];
printf("p=%p\n", p);
for (i=0; i < 3; i++) {
for (j=0; j < 3; j++)
printf ("%p:%d ", p, *p++);
printf ("\n");
}
/* Compile error: subscripted value p[0][0] is neither array nor pointer nor vector
p = &array[0][0];
printf("p=%p, p[0]=%p, p[0][0]=%p\n", p, &p[0], &p[0][0]);
*/
return 0;
}
Cast the 2D-array into 1D-array to pass it to a pointer,
And then, You are ready to access array with pointer. You can use this method to pass 2D-array to a function too.
#include <stdio.h>
int main()
{
int arr[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
arr[i][j] = (2 * i) + j;
}
}
int *Pointer = (int *)arr; // Type conversion
/*
&arr[0][0] = Pointer + 0
&arr[0][1] = Pointer + 1
&arr[1][2] = Pointer + 2
&arr[2][2] = Pointer + 3
Dereference Pointer to access variable behind the address
*(Pointer + 0) = arr[0][0]
*(Pointer + 1) = arr[0][1]
*(Pointer + 2) = arr[1][2]
*(Pointer + 3) = arr[2][2]
*/
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%d ", *(Pointer + (2 * i) + j)); // Accessing array with pointer
}
printf("\n");
}
return 0;
}
Using the function wv_matalloc from https://www.ratrabbit.nl/ratrabbit/content/sw/matalloc/introduction , you can write the following code:
#include <stdio.h>
#include "wv_matalloc.h"
int main()
{
double **matrix;
int m = 3;
int n = 4;
// allocate m*n matrix:
matrix = wv_matalloc(sizeof(double),0,2,m,n);
// example of usage:
int i,j;
for (i=0; i<m; i++)
for (j=0; j<n; j++)
matrix[i][j] = i*j;
printf("2 3: %f\n",matrix[2][3]);
}
Compile with:
cc -o main main.c wv_matalloc.c
1.
You never assigned a value to Pointer in your example. Thus, attempting to access array by Pointer invokes undefined behavior.
You need to assign Pointer by the address of the first element of array if the pointer shall be a reference:
Pointer = *array;
2.
You can't use 2D notation (p[1][1]) for a pointer to int. This is a C syntax violation.
3.
Since rows of static 2D arrays are allocated subsequent in memory, you also can count the number of array elements until the specific element of desire. You need to subtract the count by 1 since indexing start at 0, not 1.
How does it work?
Each row of array contains 2 elements. a[1][1] (the first element of the second row) is directly stored after the first two.
Note: This is not the best approach. But worth a note beside all other answers as possible solution.
#include <stdio.h>
int main (void)
{
int *Pointer;
static int array[2][2];
Pointer = *array;
Pointer[2] = 6;
printf("array[1][1] (by pointer) = %d\n", Pointer[3]);
printf("array[1][1] (by array istelf) = %d\n", array[1][1]);
}
Output:
array[2][2] (by pointer) = 6
array[2][2] (by array istelf) = 6
Side Notes:
To address the first element of the second row by array[1][2] invokes undefined behavior. You should not use this way.
"but when compiling, I get a segmentation fault error."
Segmentation fault error do not occur at compile time. They occur at run time. It just gives you the impression because high probably your implementation immediately executes the program after compilation.
I'm doing a project for school and they force us to use a type float triple pointer in a function that multiply two matrices,
and for the last day i can't figure out why when I'm using int triple pointer I get the numbers needed but when I'm using float I get zeros.
I wrote something simple just for example for the problem.
Thank you !!
int ***ptr3;
int Matrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
int i;
ptr3 = malloc(sizeof(int));
ptr3 = Matrix;
for (i = 0; i < 9; i++) {printf_s("%d ", ptr3[i]);}
printf_s("\n");
float ***ptr3_f;
float Matrix_f[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
ptr3_f = malloc(sizeof(float));
ptr3_f = Matrix_f;
for (i = 0; i < 9; i++) {printf_s("%.1f ", ptr3_f[i]);}
enter image description here
There is a whole lot of misconceptions here and your teacher does unfortunately not seem to know C very well. You simply can't use a type*** and it doesn't make any sense to use either.
A pointer of the type type*** cannot point at a 3D array of type. Nor can it point at a 2D array. It cannot point at any array type at all.
Sometimes when using dynamic memory allocation, we allocate an array of type*, each pointing at the first item in an array. A type** can then be used to point at the first type* element, to emulate the syntax of a 2D array with [i][j] access.
This does however not magically make the array of type* an array type[] at the same time. Nor does it magically make type** an array type[][]. If someone taught you that, they are confused.
Most of the time, we should not use type** to emulate a 2D array in the first place, because doing so is horribly inefficient. See Correctly allocating multi-dimensional arrays.
Thus when you attempt ptr3 = Matrix;, you get a C language constraint violation error by the compiler. Some lax compilers "only" give you a warning, but that doesn't make the code valid C. The type*** cannot be used to point at a 3D array, period.
If you somehow got the correct output in some scenario, that's by luck, since the behavior of your code isn't well-defined. On some system, int happened to have the same size as the pointer or such.
ptr3 = malloc(sizeof(int)); ptr3 = ... is senseless, since all that you achieve with the malloc is a memory leak. Because the first thing you do is to overwrite the pointer address to the data you just allocated. I'm not sure why you want to allocate a single int to begin with.
Getting rid of all misconceptions, you can perhaps salvage the program in the following manner:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int (*iptr)[3];
int imatrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
iptr = imatrix;
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
printf_s("%d ", iptr[i][j]);
}
printf("\n");
}
printf("\n");
float (*fptr)[3];
float fmatrix [3][3] = { {1.0f,2.0f,3.0f},{4.0f,5.0f,6.0f},{7.0f,8.0f,9.0f} };
fptr = fmatrix;
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
printf_s("%.1f ", fptr[i][j]);
}
printf("\n");
}
}
You don't need triple pointer for such arrays.
With:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr3_i;
int Matrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
float *ptr3_f;
float Matrix_f[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
int i;
ptr3_i = (int *)Matrix;
printf("ptr3_i:");
for (i = 0; i < 9; i++)
printf("%d ", ptr3_i[i]);
printf("\n");
ptr3_f = (float *)Matrix_f;
printf("ptr3_f:");
for (i = 0; i < 9; i++)
printf("%.1f ", ptr3_f[i]);
printf("\n");
return 0;
}
I get:
ptr3_i:1 2 3 4 5 6 7 8 9
ptr3_f:1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
Did you see the warning when you compile your code:
warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int **’ [-Wformat=]
assignment from incompatible pointer type [-Wincompatible-pointer-types]
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘float **’ [-Wformat=]
You can do something like:
ptr3 = malloc(sizeof(int**)); // allocate the memory for storing one double pointer
*ptr3 = malloc(sizeof(int*)); // allocate the memory for storing one single pointer
**ptr3 = Matrix[0]; // point to first row of the matrix
// it's similar to float pointer type
ptr3_f = malloc(sizeof(float**));
*ptr3_f = malloc(sizeof(float*));
**ptr3_f = Matrix_f[0];
Then when you want to print:
for (i = 0; i < 9; i++) {printf("%d ", (**ptr3)[i]);}
for (i = 0; i < 9; i++) {printf("%.1f ", (**ptr3_f)[i]);}
I'm writing a program to perform shellsort on an array of numbers. I first have to generate the sequence of numbers that shellsort will be performed with. This function is to generate numbers of the form 2^p*3^q that are less than the length of the array to be sorted. Then I sort the sequence array that I just generated. Here's my implementation of this:
long * Generate_2p3q_Seq(int length, int *seq_size) {
int ind = 0;
long * arr[1000];
int product;
int power = 1;
while (power < length) {
product = power;
while (product < length) {
arr[ind] = product;
product *= 3;
ind++;
}
power *= 2;
}
int i, j, k;
for (i = 0; i < ind; ++i) {
for (j = i + 1; j < ind; ++j)
{
if (arr[i] > arr[j])
{
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
*seq_size = ind;
for (int count = 0; count < ind; count++) {
printf("arr[%d] = %li\n", count, arr[count]);
}
return arr;
}
The code is meant to return a long * array and set seq_size to the length of the sequence array. For example, if I'm given an array of 16 integers to be sorted, the sequence array generated here should be 8 integers (1, 2, 3, 4, 6, 9, 8, 12) and seq_size should equal 8. I believe my understanding of pointers is wrong because my terminal output looks like this:
sequence.c: In function ‘Generate_2p3q_Seq’:
sequence.c:14:16: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
arr[ind] = product;
^
sequence.c:26:11: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
k = arr[i];
^
sequence.c:28:16: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
arr[j] = k;
^
sequence.c:34:25: warning: format ‘%li’ expects argument of type ‘long int’, but argument 3 has type ‘long int *’ [-Wformat=]
printf("arr[%d] = %li\n", count, arr[count]);
~~^ ~~~~~~~~~~
%ln
sequence.c:36:10: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
return arr;
^~~
sequence.c:36:10: warning: function returns address of local variable [-Wreturn-local-addr]
However, I'm not sure how to change this to make it work. I call this function with:
long * sequence = Generate_2p3q_Seq(size, &seq_size);
Please let me know if there's any information I've left out, I really appreciate any help.
There are two main issues here. First, you declare arr as long *arr[1000], which means it is an array of pointer to long, not an array of long. That is why you're getting about conversions between pointers and integers.
The proper way to define an array of long is:
long arr[1000];
But this then leads to the second problem, namely that you are returning a pointer to a local variable. When the function returns its local variables go out of scope, so the returned pointer no longer points to valid memory.
To fix this, declare arr as a pointer and use malloc to dynamically allocate memory for it:
long *arr = malloc((product * power) * sizeof *arr);
if (!arr) {
perror("malloc failed");
exit(1);
}
Then you can return the value of arr, which points to dynamically allocated memory.
Pass a pointer to an array as an additional parameter, and manipulate that.
void Generate_2p3q_Seq(long * arr, int length, int *seq_size) {
// Method stores result in pre-initialized arr.
}
// Call with:
long arr[1000];
Generate_2p3q_Seq(arr, length, seq_size)
// Result stored correctly in arr.
I am trying to increment an int array using a variable as the increment but it throws an error.
int array[MAXSIZE];
int n;
//fill the array with some numbers
//some other code
The situation here is that once I analyze the first "n" numbers i will not need them again and it will be a waste of cycles to iterate the array from the starting so i want to increment the array by "n".
NOTE: because of the type of the problem that I'm working on I cannot just
save the position in a variable and start from that position later using array[position]; I have to increment the pointer permanently.
array += n;
and Throws this error: incompatible type in assignment.
I don't know in advance what "n" is going to be. I tried to use
array += sizeof(int)*n; but it fails as well.
int array[MAXSIZE];
array is an array and not a pointer. You can not increment an array variable.
You can do something like:
int *p = array;
p += whatever;
just make sure that you don't deference p when it is pointing to any element beyond the last element of the array.
The fact that printing out array and p will give you the same output (address) does not make them the same things.
According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array
object has register storage class, the behavior is undefined.
So you may not change an array such a way as
array += n;
So just use one more variable of the type int *. For example
int array[MAXSIZE];
int n;
//...
int *p = array;
p += n;
an array name is a type * const array_name so you can't move it.(pay attention it is a const pointer)
you can define a pointer yourself and then move it. for example:
int *arr = new int[siz];
or in c:
int *arr = (int *)malloc(n * sizeof(int));
if your source code is in a .c file, you do not need to do casting.
If you are trying to fill the array with data, then you will need to index into the array.
int array[MAXSIZE];
int i;
for (i = 0; i < MAXSIZE; i++) {
array[i] = rand();
}
If you genuinely want to make use of a pointer, and do 'pointer arithmetic' then you must be careful.
int array[MAXSIZE];
int *p;
int i;
p = &(array[0]);
for (i = 0; i < MAXSIZE; i++) {
*p = rand();
p += 1;
}
Pointer arithmetic may not work as you expect... Doing p += 1 does not move the pointer along one byte, or even one int, but it will move the address along the size of the variable's de-referenced type.
Do an experiment:
#include <stdio.h>
void main(void) {
struct info {
int a;
int b;
};
struct info array[10];
struct info *p;
int n;
p = &(array[0]);
printf("sizeof(*p): %zu\n", sizeof(*p));
for (n = 0; n < 10; n++) {
printf("address: %p\n", p);
p += 1;
}
}
This will advance p's value by sizeof(*p) each time around the loop.
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
int main()
{
int array*,i,n;
printf("Enter size of array:\n");
scanf("%d",&n);
array = malloc(n*sizeof(int));
/* code to enter numbers in array */
array += n;
//remember to free pointers after you are done with them
free(array);
return 0;
}
This should do it.
This question already has answers here:
Why is the same value output for A[0], &A, and *A?
(4 answers)
Closed 9 years ago.
I use swapCardsRandomly(b) but when I tried swapCardsRandomly(*b) program still works without any problem.
What is the difference then?
/*
*shuffles cards randomly
*/
void shuffle( int b[][13] ) {
int counter;
int rand1 = rand() % 4;
int rand2 = rand() % 13;
b[rand1][rand2] = 1;
counter = 2;
while ( counter < 53 )
{
rand1 = rand() % 4;
rand2 = rand() % 13;
while ( b[rand1][rand2] != 0 )
{
rand1 = rand() % 4;
rand2 = rand() % 13;
}
b[rand1][rand2] = counter++;
}
swapCardsRandomly( b );
}
//for better shuffling swap elements randomly
void swapCardsRandomly( int m[][13] ) {
int temp;
int rand1;
int rand2;
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 13; j++ )
{
rand1 = rand() % 4;
rand2 = rand() % 13;
temp = m[i][j];
m[i][j] = m[rand1][rand2];
m[rand1][rand2] = temp;
}
}
}
Both b and *b have the same address (b[0][0]), check this:
int b[1][13];
printf("%p %p %p\n", (void *)b, (void *)*b, (void *)&(b[0][0]));
But there is a pointer type conflict with *b
demo.c:52:1: warning: passing argument 1 of ‘swapCardsRandomly’ from incompatible pointer type [enabled by default]
demo.c:9:7: note: expected ‘int (*)[13]’ but argument is of type ‘int *’
In a multi-dimensional array the first element, and a pointer to the first row have the same address. This is because the first element of an array has the same address as the array. So, in your case, b points to the first element of an int [][13] array and *b points to the first element of a int [13] array that happens to be the first row of an int [][13] array.
The next question is why it lets you pass *b to SwapCardsRandomly when it expects int [][13] as an argument. The answer is that arrays, including multi-dimensional arrays, are not proper types in C, so when passed in this manner it treats them as a way to interpret a pointer.
This is because value-wise both *b and b are equal that is (void*)b == (void*)(*b) == true.
b is a two-dimentational matrix =b[rand1][rand2]=1;
type of matrix name b is int[][13] that decays into address of first element that is 0th row in two dimensional array. (you can think a two dimensional array as array of one dimensional arrays).
Because b is address of 0th row, so *b decays into address of b[0][0] that is address of 0th element of 0th-row. Interesting is value (magnitude) wise both are equal that is why your code works. When your call your function with *b or b argument, address value auto typecasted into proper type int [][13].
To observe it, in your code try this printf-statement:
printf("\n %p %p\n", b, *b);
You will find both are equal!
To understand it more better with a diagram read this: A[0], &A, *A linked answer.
Because both of b and *b are equal in value but are of different types i.e both of these pointer expression are of different types but points to he same memory location.
b decays to pointer to first row (0th row) and it is of type int (*)[]. *b dereferences the pointer expression b hence
*b is of type int (*)[].Since that's an array type, it decays to a pointer to the first element of the array object. So it's of type int*.
For detailed explanation, must read this answer.