How store address of an array[] in a variable - arrays

This seems like a silly question. I have an array of chars and want to store the address of the array in another variable, but can't seem to declare the correct type for the array address (I'm using gcc):
IN:
int main(void){
char cha[] = "abcde";
char **arrayAddress = &cha;
}
OUT:
arrayaddress.c: In function ‘main’:
arrayaddress.c:3:25: warning: initialization of ‘char **’ from incompatible pointer type ‘char (*)[6]’ [-Wincompatible-pointer-types]
3 | char **arrayAddress = &cha;
| ^
This is expected, I have read elsewhere that the type of cha should be char(*)[6]. But when I try to declare arrayAddress with this type, my program fails:
IN:
int main(void){
char cha[] = "abcde";
char (*)[6]arrayAddress = &cha;
}
OUT:
arrayaddress.c: In function ‘main’:
arrayaddress.c:3:10: error: expected identifier or ‘(’ before ‘)’ token
3 | char (*)[6]arrayAddress = &cha;
| ^
make: *** [<builtin>: arrayaddress] Error 1
^
How do I define arrayAddress correctly?

It is written:
char (*arrayAddress)[6] = &cha;
Notice that the name of variable gets tucked in middle of the expression.

Arrays decay to pointers.
char cha[] = "abcde";
char *p1 = cha;
char (*arrayptr)[sizeof(cha)] = &cha;
cha, &cha[0] and &cha reference the same first element of the array cha, the only difference is the type.
cha and &cha[0] has type: pointer to char
&cha has type: pointer to array of 6 char elements.

If your compiler supports typeof extension (gcc does) then you can define the pointer as:
typeof(char (*)[6]) arrayAddress = &cha;
Or even cleaner as:
typeof(char[6]) * arrayAddress = &cha;

Related

Comparing every char in a string to a constant

Sorry, I'm relatively new to c. What I'm trying to do is loop through a string and compare each char in the string to a char. If successful, I print some value. However I'm getting a segmentation fault.
My Code:
int i;
const char* perc = '%';
char mystr[7] = "hell%o";
for(i=0;i<sizeof(mystr);i++){
if(strcmp(mystr[i],perc)!=0){
printf("%d",i);
}
NOTE: I'm not using % for format strings here, I'm literally just looking for its position in the string.
Thank you.
strcmp() is for comparing strings. To compare characters, you can use == operator.
Also note that sizeof is not for getting length of strings but getting number of bytes used for the type. In this case it is used for char array, so it may work according to what you want to do because sizeof(char) is defined to be 1 and therefore the number of bytes will be equal to the number of elements. Note that the terminating null-character and unused elements after that will added to the count if they exists. To get the length of string, you should use the strlen() function.
int i;
const char perc = '%'; /* use char, not char* */
char mystr[7] = "hell%o";
int len = strlen(mystr); /* use strlen() to get the length of the string */
for(i=0;i<len;i++){
if(mystr[i] != perc){ /* compare characters */
printf("%d",i);
}
if(strcmp(mystr[i],perc)!=0){
Must be if(mystr[i]!= perc){. And const char* perc = '%'; should be const char perc = '%';
strcmp takes two strings (char*), but you are passing chars. Compiling with gcc and -Wall shows:
c.c: In function ‘main’:
c.c:5:20: warning: initialization of ‘const char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
5 | const char* perc = '%';
| ^~~
c.c:9:24: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]
9 | if(strcmp(mystr[i],perc)!=0){
| ~~~~~^~~
| |
| char
In file included from c.c:1:
/usr/include/string.h:137:32: note: expected ‘const char *’ but argument is of type ‘char’
137 | extern int strcmp (const char *__s1, const char *__s2)
| ~~~~~~~~~~~~^~~~
Always remember: The compiler is one of the best friends of you.
The fixed program could be:
#include <stdio.h>
#include <string.h>
int main() {
int i;
const char perc = '%';
char mystr[7] = "hell%o";
for (i = 0; i < sizeof(mystr); i++) {
if (mystr[i] != perc) {
printf("%d", i);
}
}
}

correct return type for C function?

I am using an array of strings inside my function declared like this
char (*array)[PATH_MAX] = malloc (1000 * sizeof *array);
Allocating 1000 char pointers of size PATH_MAX (1024).
I want the function to return that specific data structure, i.e. return the pointer array. But I can't manage to choose the correct return type.
warning: returning 'char (*)[1024]' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
I get that I can't have int as return type, but char** doesn't work either.
warning: returning 'char (*)[1024]' from a function with incompatible return type 'char **' [-Wincompatible-pointer-types]
I've tried using char (*)[1024] as return type, but it gives me generic C error messages, leading me to believe that I am not using the correct syntax.
error: expected identifier or '(' before ')' token
38 | char (*)[1024] read_dir (char *path) {
| ^
Is there a correct syntax for achieving this or am I just doing it wrong?
You need to define the function as follows:
char (*read_dir(char *path))[PATH_MAX] {
This specifies the return type as a pointer to an array of size PATH_MAX of char *.
Time for typedef
typedef char arr1k_char[1000];
arr1k_char *foo(int n) {
arr1k_char *x = malloc(n * sizeof *x);
return x;
}
https://ideone.com/Cqxa61

Do matrices work within structs in C?

I'm trying to make a struct that contains (in this example) the name of the item to buy in an array and in a matrix it's price and the weight of it I should buy. This is just an easy example of what i'm trying to do.
I use strcpy to declare the value just because I learned it this way, I don't if it's the best of the methods.
#include<stdio.h>
#include<string.h>
typedef struct Grocery_list{
char item_name[2];
double item_info[2][2];
}Grocery;
int main(){
Grocery market;
strcpy( market.item_name[0], "Apple");
strcpy( market.item_name[1], "Sugar");
strcpy( market.item_info[0][0],200); //apple weight
strcpy( market.item_info[1][0], 3); //apple price
strcpy( market.item_info[0][1], 300);
strcpy( market.item_info[1][1], 4);
printf("%f \n",martket.item_info[1][1]);
return 0;}
The errors are
teste.C: In function ‘int main()’:
teste.C:14:27: error: invalid conversion from ‘char’ to ‘char*’ [-fpermissive]
strcpy( market.item_name[0], "Apple");
^
In file included from teste.C:2:0:
/usr/include/string.h:129:14: error: initializing argument 1 of ‘char* strcpy(char*, const char*)’ [-fpermissive]
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
teste.C:15:27: error: invalid conversion from ‘char’ to ‘char*’ [-fpermissive]
strcpy( market.item_name[1], "Sugar");
^
In file included from teste.C:2:0:
/usr/include/string.h:129:14: error: initializing argument 1 of ‘char* strcpy(char*, const char*)’ [-fpermissive]
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
teste.C:16:35: error: cannot convert ‘double’ to ‘char*’ for argument ‘1’ to ‘char* strcpy(char*, const char*)’
strcpy( market.item_info[0][0],200);
^
teste.C:17:34: error: cannot convert ‘double’ to ‘char*’ for argument ‘1’ to ‘char* strcpy(char*, const char*)’
strcpy( market.item_info[1][0], 3);
^
teste.C:18:36: error: cannot convert ‘double’ to ‘char*’ for argument ‘1’ to ‘char* strcpy(char*, const char*)’
strcpy( market.item_info[0][1], 300);
^
teste.C:19:34: error: cannot convert ‘double’ to ‘char*’ for argument ‘1’ to ‘char* strcpy(char*, const char*)’
strcpy( market.item_info[1][1], 4);
^
teste.C:21:16: error: ‘martket’ was not declared in this scope
printf("%f \n",martket.item_info[1][1]);
^
Obviously, I searched for answers and solutions on Google, but everything I tried just caused other errors or even the same. For I'm new in programming in general I don't know what those errors mean.
Thank you in advance
Three issues:
Your struct doesn't have an array of strings. It has an array of characters. You need to add an extra dimension to item_name to have such an array:
typedef struct Grocery_list{
char item_name[2][50];
double item_info[2][2];
}Grocery;
Also, you're using strcpy to attempt to copy numerical values. This function is used for copying strings. Instead of using this function, perform a simple assignment:
market.item_info[0][0] = 200; //apple weight
market.item_info[1][0] = 3; //apple price
market.item_info[0][1] = 300;
market.item_info[1][1] = 4;
Lastly, you have a typo in your printf statement:
printf("%f \n",martket.item_info[1][1]);
It should be:
printf("%f \n",market.item_info[1][1]);
The member item_name is an array of two characters, it's not an array of strings, it's just a single string (which can only hold a single character, remember that all strings have a special terminator character). You probably should make this an array of arrays of char, which means it's an array of strings:
char item_name[2][64]; // Two strings, each can hold 63 characters
The member item_info is an array of arrays of double. The strcpy function is for copying strings (arrays of char).
Remember that each element in an array is like a variable, which means you can just assign to it:
market.item_info[0][0] = 200; //apple weight
market.item_info[1][0] = 3; //apple price
market.item_info[0][1] = 300;
market.item_info[1][1] = 4;
And the last error is because you misspelled market.
All of this would be very obvious even to a beginner if you just read the error messages.
1 - your declaration of the item_name[2] is correct but you used in the wrong way. this is actually logical error. you need enough room for saving your data such as: apple, sugar and ... the last character of string is '\0'. indeed you just declaring one character for saving "apple" or "sugar".
2 - strcpy is for manipulating of string or array of characters, so you are not authorized to use this function with numerical variables.
3 you have misspelling in last line (before returning to OS).

what is wrong in this strcmp()?

I try to write simple C function with strcmp(). But I always get Segmentation fault (core dumped). What is wrong ?
char *arr={"abcdefg"};
char *a = arr[1];
if(strcmp(a, 'b') == 0)
{
printf("it is b \n");
}
What is wrong?
You did not let yourself be helped by the compiler.
Using -Wall -Wextra on GCC (which is by no means the best you can get but rather the bare minimum you should always use), I get:
testme.c: In function ‘main’:
testme.c:6:11: warning: initialization makes pointer from integer without a cast [enabled by default]
char *a = arr[1];
^
You took arr[1] -- which is the char value 'b' -- and turned it into a char *. Your a is now pointing to whatever is at address 0x62 (assuming ASCII), which is most definitely not what you intended. You probably wanted &arr[1], or arr + 1.
Or you wanted a char -- then you shouldn't declare char *, and strcmp() would be the wrong thing to use in the first place.
testme.c:8:1: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if(strcmp(a, 'b') == 0)
^
In file included from testme.c:1:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘int’
extern int strcmp (const char *__s1, const char *__s2)
^
strcmp() expects two C strings (char const *). Your second argument 'b' is of type int... you probably wanted "b".
Which still would not compare equal, because "bcdefg" is not equal "b"...
Or you wanted a one-character comparison... that would be if ( a == 'b' ) then, with a being of type char, not char * (see above).
testme.c:10:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf("it is b \n");
^
testme.c:10:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
Please do us all the favour of posting complete code, includes, int main() and all, so we can copy & paste & compile, and still have line numbers match.
I think this is what you have been trying to achieve :
#include <stdio.h>
#include <string.h>
int main(void)
{
char *arr = {"abcdefg"};
char a = arr[1];
if( a == 'b' )
{
printf("it is b \n");
}
}
You're doing a number of things wrong here. strcmp is for comparing strings. The simplest way to do what you want is
char *arr= {"abcdefg"};
char a = arr[1];
if(a == 'b')
{
printf("it is b \n");
}
If you still want to do it with strcmp, you need to make a a string by appending the null terminator \0 to it.
char *arr= {"abcdefg"};
char a[] = {arr[1], '\0'};
if(strcmp(a, "b") == 0)
{
printf("it is b \n");
}

Pass a char pointer array to a function in C?

I have the following code:
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(n *sizeof *array);
/*Some code to assign array values*/
test(a, array);
return 0;
}
int test(char s1, char **s2){
if(strcmp(s1, s2[0]) != 0)
return 1;
return 0;
}
I'm trying to pass char and char pointer array to a function, but the above code results in the following errors and warnings:
temp.c: In function ‘main’:
temp.c:6:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
temp.c:6:13: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
temp.c:10:5: warning: implicit declaration of function ‘test’ [-Wimplicit-function-declaration]
temp.c: At top level:
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
temp.c: In function ‘test’:
temp.c:16:5: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
I'm trying to understand what the problem is.
First of all, you should include the necessary header files. For strcmp you need <string.h>, for malloc <malloc.h>. Also you need to at least declare test before main. If you do this you'll notice the following error:
temp.c: In function ‘test’:
temp.c:20:5: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
/usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
This indicates that test() should have a char * as first argument. All in all your code should look like this:
#include <string.h> /* for strcmp */
#include <malloc.h> /* for malloc */
int test(char*,char**); /* added declaration */
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(sizeof(*array));
array[0] = malloc(n * sizeof(**array));
/*Some code to assign array values*/
test(a, array);
free(*array); /* free the not longer needed memory */
free(array);
return 0;
}
int test(char * s1, char **s2){ /* changed to char* */
if(strcmp(s1, s2[0]) != 0) /* have a look at the comment after the code */
return 1;
return 0;
}
Edit
Please notice that strcmp works with null-terminated byte strings. If neither s1 nor s2 contain a null byte the call in test will result in a segmentation fault:
[1] 14940 segmentation fault (core dumped) ./a.out
Either make sure that both contain a null byte '\0', or use strncmp and change the signature of test:
int test(char * s1, char **s2, unsigned count){
if(strncmp(s1, s2[0], count) != 0)
return 1;
return 0;
}
/* don' forget to change the declaration to
int test(char*,char**,unsigned)
and call it with test(a,array,min(sizeof(a),n))
*/
Also your allocation of memory is wrong. array is a char**. You allocate memory for *array which is itself a char*. You never allocate memory for this specific pointer, you're missing array[0] = malloc(n*sizeof(**array)):
array = malloc(sizeof(*array));
*array = malloc(n * sizeof(**array));
Error 1
temp.c:6:13: warning: incompatible implicit declaration of
built-in function ‘malloc’ [enabled by default]
Did you mean this?
array = malloc(n * sizeof(*array));
Error 2
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t
match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
You are passing the address of the first element of an array a:
test(a, array);
So the function signature should be:
int test(char* s1, char** s2)
You have several problems. The first is that the prototype is wrong. The data type for a decays to a char pointer when passing to a function, so you need:
int test (char* s1, char** s2) { ... }
However, even when you fix this, the test declaration isn't in scope when you first use it. You should either provide a prototype:
int test (char* s1, char** s2);
before main, or simply move the whole definition (function) to before main.
In addition, don't forget to #include the string.h and stdlib.h headers so that the prototypes for strcmp and malloc are available as well.
When you pass an array of char to your function, the argument decays to a pointer. Change your function arguments to
int test(char* s1, char **s2);
^
^
and your code should at least compile

Resources