This code take 5 strings and sort them in ascending way.
void swap (char data[5][255], int i, int j) {
char temp[255];
strcpy(temp,data[i]);
strcpy(data[i],data[j]);
strcpy(data[j],temp);
}
void sort (char data[5][255], int n) {
// * : first address contact
int i, j;
for(i = 0; i < n-1; i++)
for( j = i+1; j > 0; j--)
if(strcmp(data[j-1],data[j])>0)
{
printf("%s",data[j-1]);
swap(data, j-1, j);
}
}
int main() {
char strings[5][255];
char comp[255];
int i, n;
n = sizeof(strings)/sizeof(comp);
printf("Enter 5 strings, max 255 chars each:\n");
for(i=0; i < n; i++)
scanf("%s",strings[i]);
sort(strings, n);
printf("Sorted data:\n");
for(i=0; i < n-1; i++)
printf("%s, ",strings[i]);
printf("%s.\n",strings[i]);
return 0;
}
In addition of that, how can I possibly parse my static array string[5][255] to function by using pointer?
I tried that, for example,
void sort ( char **data, int i ) { ... }
but it throws out error like this.
incompatible pointer types passing 'char [5][255]' to parameter of type 'char **'
Is there anything I can parse my array using pointer?
Since array parsed to function its first address(pointer), I thought function will accept those expression. Please give me some advice to understand.
The parameter you must pass is not a pointer to a pointer char**, but a pointer to a char array char(*)[255]
void sort (char (*data)[255], int n)
When you pass an array, you can omit the size of the first dimension
void sort (char data[][255], int n)
which is equivalent to char(*)[255].
char** is a pointer, which points to another pointer. Whereas char(*)[255] is a pointer, which points to an array.
You have to understand the difference between: char **data vs char (*data)[255]
Those are two different types because the allocation of memory may be different:
When char **data is used pointer arithmetic may not work properly, meaning data could be scattered all over the memory
When char (*data)[255] is used pointer arithmetic works perfectly because all elements of array are adjacent to each other
As I wrote you in the comment char[][] doesn't decay to char** but it decays to char(*)[] ( char (*data)[255] in your case) as the first element decay in a pointer which is not a "pointer to a pointer" but a pointer to an array of 255 characters. It is possible to use a char** pointer if you do something like this (c++):
char **array = new char *[N];
for(int i = 0; i<N; i++)
array[i] = new char[N];
or using the malloc (c).
As #newact suggests it is important to distinguish between
char *data[255] -> char *[255]data = => "data is an array of 255 pointers to char"
And
char (*data)[255] -> char [255](*data) => "data is a pointer to an array of 255 chars"
Try to make the following changes:
void swap ( char *data, int i, int j)
*(data + index1*255 + index2)
Related
I am trying to initialize matrices in a helper function, but I am getting a warning accessing the matrix inside the helper function that I can't figure out how to fix. I was reading about multidimensional arrays and even saw the same notation used to pass and access a matrix in multiple examples, but mine generates a warning and I'm not quite sure why.
To my knowledge this error means that the argument is not of a type the function is expecting, but I was using it just fine inside the main function before relocating the initialization into its own function. This leads me to think that I'm doing something wrong when passing the matrix to the helper function.
passing argument 1 of 'memmove' makes pointer from integer without a cast [-Wint-conversion]
Here's my code for the initializer. p is a pointer to data inside an array that I want to initialize into my matrix. I'm using this type of nested for loop to spread 16 bytes of data coming from p into my matrix 1 byte per cell.
void initialize(const unsigned char *p, unsigned char (*matrix)[4]) {
for (unsigned int i = 0; i < 4; i++){
for (unsigned int j = 0; j < 4; j++){
memmove(matrix[i][j], p + (4*i+j), 1); <--- Warning here
};
};
};
Initialize is being called in another function like this:
void func(const unsigned char *p) {
unsigned char matrix[4][4] = {
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0}
};
initialize(p, matrix);
};
Function memmove() takes a pointer as the first argument. While matrix[i][j] is a char, a type from integer family. Assingning an integer other than constant 0 to a pointer require a cast. Otherwise a warning is raised.
Therefore I expect that in order to copy a single char you should pass a pointer to element matrix[i][j]. Pointers are formed by applying & operator to objects.
memmove(&matrix[i][j], p + (4*i+j), 1);
however it can written far simpler, more readable and likely more optimal as:
matrix[i][j] = p[4 * i + j];
or even by copying the whole array without any loops:
memmove(matrix, p, 16);
passing argument 1 of 'memmove' makes pointer from integer without a cast [-Wint-conversion]
Instead of passing an integer value as the destination:
unsigned char (*matrix)[4]
...
// v----------v This is an integer of type unsigned char
// memmove(matrix[i][j], p + (4*i+j), 1);
Pass the address of the integer as the destination:
memmove(&matrix[i][j], p + (4*i+j), 1);
// ^-----------^ This is an address
void *memmove(void *s1, const void *s2, size_t n); expects s1 to be an address.
matrix in func() is a matrix, aka "2-D array".
matrix in initialize() is not really a matrix, but a pointer to an array[4] of unsigned char.
Since C99 and selectively afterwards, code can use a variable length array notation.
void initialize(size_t rows, size_t cols, unsigned char (*m)[rows][cols],
const unsigned char *p) {
printf("%zu %zu %zu\n", rows, cols, sizeof *m);
for (size_t r = 0; r < rows; r++){
for (size_t c = 0; c < cols; c++){
(*m)[r][c] = *p++;
}
}
}
#define ROW 5
#define COL 7
int main(void) {
unsigned char matrix[ROW][COL];
unsigned char bytes[sizeof matrix] = "Something abcde fghij klmno pqrst uvwxy z";
size_t r = sizeof matrix / sizeof matrix[0];
size_t c = sizeof matrix[0] / sizeof matrix[0][0];
printf("%zu %zu %zu\n", r, c, sizeof matrix);
initialize(r, c, &matrix, bytes);
}
Learning C and this confusing me:
#include <stdio.h>
int main(){
int m[5][5];
int count = 0;
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
m[i][j] = count++;
}
}
int **p = m;
int (*k)[5] = m;
printf("%p\t%p\t%p", *p, *k, *m);
return 0;
}
that's what has been printed:
0x100000000 0x7ffff1fc9d70 0x7ffff1fc9d70
I'm really confused why dereference *p is 0x100000000, shouldn't it be 0x7ffff1fc9d70?
You’re thinking that m is of type int **, right?
It’s not. If you had done this, it would be:
int *m[5];
That make an array of five pointers to int, so m would be pointer to pointer to int.
However, if you do this:
int m[5][5];
You get enough space for 25 ints, which the compiler will access as a 5x5 two-dimensional array. p points to the beginning of that array. Dereference it, and the compiler reads the beginning of that array and interprets it as a pointer to int. Change the numbers you’re filling it with, and you’ll get different pseudo-pointers.
I'm trying to write a function that prints the elements of a given array. However, I don't understand how I can count the elements of the array which is passed into my function. Here's the code:
In this example, I am trying to get the count from within my function, though this only returns 1.
#include <stdio.h>
void first_function(int ages[], char *names[]) {
int i = 0;
int count = sizeof(*ages) / sizeof(int);
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
first_function(ages, names);
printf("---\n");
return 0;
}
In this example, I give the function an extra parameter (count), then get the count from within main. Is this the normal way to do it? It seems unclean somehow.
#include <stdio.h>
void first_function(int ages[], char *names[], int count) {
int i = 0;
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
int count = sizeof(ages) / sizeof(int);
first_function(ages, names, count);
printf("---\n");
return 0;
}
Your so-called unclean way is the normal way. (The sizeof idiom does not work if the array parameter has decayed to a pointer type). Although consider using a size_t type for the count, not an int.
Another approach is to use a particular value to signal the end of the array. Effectively this is how the string library functions work in C; with NUL signalling the end of the string.
According to the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if any)
are those specified within the [ and ] of the array type
derivation....
So this function declaration
void first_function(int ages[], char *names[]);
is equivalent to the following declaration after adjusting the corresponding parameters declared like arrays.
void first_function( int *ages, char **names );
That is the parameters ages and names have pointer types within the function.
As result this expression
int count = sizeof(*ages) / sizeof(int);
(I think you mean
int count = sizeof(ages) / sizeof(int);
^^^^
nevertheless)
is equivalent to
int count = sizeof( int) / sizeof(int);
because the type of the sub-expression *ages is int.
If you will write the expression like
int count = sizeof(ages) / sizeof(int);
then it is equivalent to
int count = sizeof(int *) / sizeof(int);
and again will not yield the size of the array passed as the argument.
For such arrays that do not have a sentinel value you have to pass also their sizes to functions if it is required.
Thus the function should be declared like
void first_function(int ages[], char *names[], size_t n);
and called like
size_t count = sizeof(ages) / sizeof(*ages);
first_function(ages, names, count);
Pay attention to that there is no need to initialize the variable i within the function two times. The function can look like
void first_function(int ages[], char *names[], size_t count)
{
for ( size_t i = 0; i < count; i++)
{
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
Yes you can't use sizeof here to get the length of the array in the called function. Because array decays into pointer here in the called function. And that's why it will return sizeof pointer not size of array.
Solution- you need to pass another parameter specifying the size of the array or keeping a place holder like NULL or some value to mark the end of the array. (Well you have followed that in your second solution - which is perfectly fine and it works).
Return value of sizeof is size_t. Use size_t instead of int.
It's the right way to handle what sizeof operator returns.
code:
int arr[5] = {1,2,3,4,5};
int (*p)[5] = &arr;
printf("p:%p\n",p);
printf("*p:%p\n",*p);
result: p = *p = arr = 0x7ffee517c830 they are all the address of the array
The right way to use p to visit arr[i] is *(*p+i)
The type of pointer p is int(*)[5], so p point to an array which type is int [5]. But we can't say that p point to an invisible shell of arr, p is a variable after all. It stores the address of arr, which is also the address of arr[0], the first element of arr.
I thought *p will get me 1, which is the first element of arr.
The dereference operation means take the value in p as address and get the value from this address. Right?
So p stores the address of arr,which is 0x7ffee517c830 here, and 1 is stored in this address. Isn't **p illegal? The first dereference give us 1, and second dereference will use 1 as address which is illegal.
What I am missing?
The result of *p is an lvalue expression of array type. Using (*p) is exactly the same as using arr in any expression you could now think of.
For example:
&*p means &arr
**p means *arr (which is legal).
(*p)[i] means arr[i].
sizeof *p means sizeof arr.
Arrays are not special in this regard. You can see the same phenomenon with int x; int *q = &x;. Now *q and x have exactly the same meaning.
Regarding your last paragraph, I think you are confusing yourself by imagining pointers as glorified integers. Some people teach pointers this way but IMO it is not a good teaching technique because it causes the exact confusing you are now having.
If you dereference an int(*)[5] you get an int[5] and that's all there is to it. The data type matters in dereferencing. It does not make sense to talk about "dereferencing 0x7ffee517c830". Again this is not peculiar to arrays; if you dereference a char ***, you get a char ** etc.
The only way in which arrays are "different" in this discussion is what happens if you try to do arithmetic on them, or output them, etc. If you supply an int[5] as a printf argument for example, there is implicit conversion to int * pointing at the first of those 5 ints. This conversion also happens when applying the * operator to an int[5], which is why you get an int out of that.
p is declared as a 'pointer to int[5]'.
arr is declared as an 'int[5]`
so the initializer p = &arr; is not really that strange. If you substituted any primitive type for int[5] you wouldn't bat an eye.
*p is another handle on arr. so (*p)[0] = 1.
This really only comes up in wierd cases. It's most natural where you dereference the pointer-to-array using the subscript operator. Here's a contrived example where I want to pass a table as argument.
#include <stdio.h>
int print_row_range(int (*tab) [2], int first, int last)
{
int i;
for(i=first; i<= last; i++)
{
printf("{%d, %d}\n", tab[i][0], tab[i][1]);
}
}
int main(int argc, char *argv[])
{
int arr[3][2] = {{1,2},{3,4},{5,6}};
print_row_range(arr,1,2);
}
This example treats the table as an array of rows.
Dereferencing doesn't give you a value. It gives you an object, which can be used as a value of its type if it can be converted to.
*p, being identical to arr, is an object of an array of 5 ints, so if you want to get an integer from the array, you must dereference it again like (*p)[3].
Consider a bigger example:
int arr[5][5];
int (*p)[5] = arr;
Now you get arr[0] with *p, which itself is an array of 5. Here comes the difference:
*( p+1) == arr[1];
*(*p+1) == arr[0][1];
^ ^^^
Got the point?
One use case is to be able to allocate with malloc an 2D (or more) pointer of arrays with only one malloc:
#include <stdio.h>
#include <stdlib.h>
static int (*foo(size_t n))[42] {
return malloc(sizeof *foo(0) * n);
// return malloc(sizeof(int [n][42]); works too
}
int main(void) {
size_t n = 42;
int (*p)[42] = foo(n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}
I think this very funny.
One more with VLA:
#include <stdio.h>
#include <stdlib.h>
static void *foo(size_t elem, size_t n, size_t m) {
return malloc(elem * n * m);
}
int main(void) {
size_t n = 42;
int (*p)[n] = foo(sizeof **p, n, n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}
I'm learning c and I'm finding difficulties with the expression (int*)arr in the line 18. The whole program is
int main () {
char c, arr['z'-'a'], *pChar;
int i, *pInt, int matr = 74 ;
for ( c='a'; c<'z'; c++) {
arr[c-'a'] = c;
printf("%c ", arr[c-'a']);
}
printf("\n");
pChar = arr + matr%15;
for (i=0; i< 5; i++) {
printf("%c ", *pChar);
pChar++;
}
printf("\n");
pInt = (int *)arr + matr%2;
for (i=0; i<5; i++) {
pChar = (char *)pInt;
printf("%c ", *pChar);
pInt++;
}
return 0;
}
Thank you
You declared arr as char type. As the name of an array can be used as a pointer to its first element ; arr is a pointer to first char of array arr and is of type char *.
pInt is of type int *, for the expression
pInt = (int *)arr + matr%2;
a cast is needed to covert arr to int * type in your program.
In C when the name of an array is used as a value it represents the address of the first element (&arr[0]).
In first case (line 11) you have pChar = &arr[matr%15] because pChar is a char*
In second case (line 18) you have pInt = (int *) &arr[matr%15]. You have to cast pointer to char into pointer to int, bacause pInt is a int*
The other answers have been telling you that you need to use a cast to convert arr to int*.
Better: Don't convert arr to int*.
char c, arr['z'-'a'], *pChar;
int i, *pInt, int matr = 74 ;
This would be clearer if you'd declare each variable on a line of its own:
char c;
char arr['z'-'a'];
char *pChar;
int i;
int *pInt;
int matr = 74;
You've declared arr as an array of char. Assuming an ASCII character set, it has 26 characters. You probably wanted it to have 26.
An expression of array type is implicitly converted, in most contexts, to a pointer to its first element. So arr usually becomes an expression of type char*, equivalent to &arr[0].
Converting that char* pointer to int* (which does require a cast) gives you a pointer to an int that overlays the first sizeof (int) elements of the array.
That's a very odd thing to do, and it actually has undefined behavior (arr doesn't necessarily have the proper alignment to store int objects).
If you want to store int objects, declare an array of int.
I haven't studied your code enough to understand what it's intended to do, but there's almost certainly a better way to do it.