How to loop through an array declared in the header file? - c

I have declared my header file with a structure consisting of arrays. It looks like this:
#ifndef HEADER_H_
#define HEADER_H_
typedef struct{
uint32_t State[3];
}h_t;
#endif
The C file that accesses this header file looks as follows:
#include"Header.h"
#include<stdio.h>
#include <stdlib.h>
char* old_states[3];
old_states[0] ="ABC";
old_states[1] ="BAC";
old_states[2] ="AAC";
h_t var;
for(i=0; i<3;i++){
var.State[i] = old_states[i];
printf("\n The state is %s", var.State[i]);
}
I print the states out to check them. THey are:
The state is ABC
The state is BAC
The state is AAC
Now I want to loop through each var.State[n], like var.State[0], var.State[1], var.State[2] individually.
That is loop through var.State[0] ="ABC" so that I could access each of the letters(A,B,C) individually. Can somebody tell me how could I achieve this?

In your code, old_states[n]is of char *, a pointer. OTOH, var.State[i] is of type uint32_t and they are not same.
A pointer type maybe converted to an integer type, but the result is strictly implementation dependent. To take this further, as stated in C11, chapter §6.3.2.3,
If the result cannot be represented in the integer type, the behavior is undefined.
So, basically you should avoid doing this unless you really really know what you're doing.
Then, in case of
printf("\n The state is %s", var.State[i])
%s expects a char * (a pointer to the initial element of an array of character type, to be exact, and in case the precision is not specified, it should be null-terminated), but what you're passing is uint32_t. It is called undefined behaviour again, as per the above point.
Moral of the story: enable compiler warnings and pay heed to them.
Solution:
Preferable, change your structure member type from
uint32_t State[3];
to
char * State[3];
then, assign them as you're doing now and finally, for accessing all individual elements, you can do something like (pseudocode)
for(i=0; i<3;i++)
{
int len = strlen(var.State[i]);
for(j=0; j < len ;j++) printf("%c \t", var.State[i][j]);
printf("\n");
}

As you declared uint32_t State[3]; and printing it with %s specifier that creates problem.
You can declare State[3]; as a 2-D character array like this -
EDIT
char State[3][4];
And to store values -
for(i=0;i<3;i++)
{
memcpy(var.State[i],old_states[i],strlen(old_states[i]);
}
And access each character like this -
var.State[i][j]
To print each character
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%c",var.State[i][j]);
}
printf("\n");
}

Related

Structure wrapper and variable array size

I often use :
Array wrappers to pass array by value but the problem is that the size of array is determined at compile time (see part I of the code)Array declarations that depend of a variable (see part II of the code)
How is it possible to "combine" these two types of code to have array wrappers that depends of a variable ? (see part III of the code. I know it can not work because there is a variable in structure declaration, it is just here to give an idea)
#include <stdio.h>
int main() {
// First part of code
// Array wrapper to pass array by value but size of array is determined at compile time
struct S {int m_array[5];} myarray={1,2,3,4,5};
struct S myarraycopy;
struct S copyarray(struct S a) { return a ;}
myarraycopy=copyarray(myarray);
for (int i=0;i<5;i++) printf("%d \n",myarraycopy.m_array[i]);
// Second part of code
// Array declaration is function of a variable n and
// so it is not determined at compile time
int n;
printf("Size : ");scanf("%d",&n);
int myarray1[n];
for (int i=0;i<n;i++) myarray1[i]=i;
printf("Array size %d \n",sizeof(myarray1));
for (int i=0;i<n;i++) printf("%d \n",myarray1[i]);
/* How to combine the two parts above ???
int n1;
printf("Size : ");scanf("%d",&n1);
struct S1 {int m_array[n1];} myarray1;
struct S1 myarraycopy1;
struct S1 copyarray1(struct S1 a) { return a ;}
myarraycopy1=copyarray1(myarray1);*/
}
How is it possible to "combine" these two types of code to have array wrappers that depends of a variable ?
You cannot, at least in standard C. In the standard's terms, the members of a structure type cannot be variably-modified. This serves the purpose that the size of a structure type is always a compile-time constant (even, technically, structure types having flexible array members).
In the general case, you have the alternative of passing your array normally, in the form of a pointer to its first element. You may declare the function parameter as a pointer to const elements, so that the function cannot modify the array (at least, not without casting away the constness, which you could surely persuade your compiler to warn about).
That does not serve your copyarray() use case, because you cannot return arrays (as such) either, nor assign to whole arrays. But memcpy() does that job fine without need for wrapping or passing around arrays by value, so the case seems contrived.
I try to use flexible array member (see code below). I am not surprised that this code does not work. Indeed, the size of the flexible array is not know at compile time (cf standard 6.7.2.1 *s1=*s2;). But, as the size of myarray1 is known ( sizeof(S1)+n1*sizeof(int) ), I wonder if Inline Assembly Language in the code could be used to force the copy of the whole variable myarray1.
#include <stdio.h>
typedef struct {int l;int m_array[];}S1;
void myfoo(S1 a) {
for (int i=0;i<a.l;i++) a.m_array[i]*=10;
printf("in myfoo\n");
for (int i=0;i<a.l;i++) printf("%d \n",a.m_array[i]);
}
int main() {
int n1;
printf("Size : ");scanf("%d",&n1);
S1 *myarray1=malloc(sizeof(S1)+n1*sizeof(int));
myarray1->l=n1;
for (int i=0;i<n1;i++) myarray1->m_array[i]=i;
myfoo(*myarray1);
printf("in main\n");
for (int i=0;i<n1;i++) printf("%d \n",myarray1->m_array[i]);
}

Access a 2D array[x][y] as a 1D array[z] in C

I recently started writing chunks of C code as part of my university's programming lessons (so you can freely assume that I am a complete idiot). I'm trying to write a function that writes a 2D array's data to a file, but I'm having difficulties. I declare the array in main, I have its x and y dimensions saved as #defines, and I want to call my function() like so;
include "function.h"
#define /* x_res, y_res */
int main(){
static unsigned char pic[x_res][y_res];
/* do some operations on pic*/
function(pic,x_res,y_res);
}
The function itself is saved in a header file and is intended to be included at the very top of my main .c file. It goes something like this;
void function(unsigned char arry,int x_res,int y_res){
/* some calculations, declaring file pointer with fopen() */
for(int i=0;i<y_res;i++){
for(int j=0;j<x_res;j++){
fprintf(f,"%c",arry[i][j]);
}
}
}
I'm greeted with an error in the line fprintf(f,"%c",arry[i][j]); saying that the "subscripted value is neither array nor pointer nor vector", which is false since I know that arry is an array. Furthermore, if I try to replace said line with something like fprintf(f,"%c",arry[i*j+j]);, the error goes away, but the file output is gibberish (I'm assuming I'm only printing the addresses of the first-dimension elements of arry).
The question, then; Why can't 2D arrays be accessed like their 1D counterparts, and how do I work around this? I would imagine that an int array[][]={{0,1},{2,3}}; would give an output of
array[0] -> 0
array[1] -> 1
array[2] -> 2
array[3] -> 3
, but this is not the case -- it prints 0, 2, and then two memory addresses.
I've tried declaring my function to accept arguments as void function(unsigned char arry[*value of x_res*][*value of y_res*],x_res,y_res), which works but is not how I would like the function to work.
I've looked at some other online examples but it seems few people have had a similar problem. I tried some answers from this question but again things do not work. For example, using void function(unsigned char **arry,x_res,y_res) works with accessing the array as 2D (arry[i][j]), but again, like with the example above, most values (all that aren't in the first column) are trash.
In C99 and later, it is possible to have a VLA
void function(int x_res, int y_res, int char[][y_res])
{
for(int i=0;i<x_res;i++)
{
for(int j=0;j<y_res;j++)
{
fprintf(f,"%c",arry[i][j]);
}
}
}
The problem is that support of an implementation for VLAs was made optional in C11 (i.e. a C11 compiler is not required to support them). And VLAs are definitely not supported in C90 (the ISO C standard of 1990).
An declared array is contiguous in memory, so can be treated like a flat 1D array. For example;
void function2(int x_res, int y_res, unsigned char *arr)
{
for(int i=0;i<x_res;i++)
{
for(int j=0;j<y_res;j++)
{
fprintf(f,"%c",arr[i*y_res + j]);
}
}
}
int main()
{
unsigned char x[10][20];
unsigned char y[10*20];
unsigned char *z = malloc(10*20*sizeof(*z));
/* initialise elements x, y, and z */
function2(10,20, (unsigned char *)x);
function2(10,20, &x[0][0]);
function2(10,20, y);
function2(10,20, z);
}
The type conversion in the first call of function() is needed since a 2D array of unsigned char cannot be implicitly converted to a unsigned char *. However, the address of x and the address of x[0][0] have the same value, even though they have different types.
A gotcha with this technique is that the dimensions passed (first two arguments of function2()) are not checked at compile time. For example;
int xx[5][6];
function2(10, 20, (unsigned char *)xx); /* danger, Will Robinson!! */
function2(10, 20, &xx[0][0]); /* danger, danger!! */
will compile but, since the dimensions of xx are less than the first two arguments tell function2() to expect, will cause function2() to have undefined behaviour for both calls.

C - struct* cast at runtime?

Assuming I have the following code:
struct str1
{
int common1;
char common2;
char *common3;
long int aaaaaaaa;
}
struct str2
{
char bbbb;
char *common3;
int common1;
char common2;
}
struct str3
{
char ccccccccc[200];
int common1;
char common2;
int dddddddd;
int eeeeeeee;
char *common3;
}
void somefunc1(struct str1 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
void somefunc2(struct str2 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
void somefunc3(struct str3 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
Can I somehow avoid code duplication and use a single generic function? Function calls are to be decided at runtime, therefore a macro is irrelevant. All the difference between the functions is the structs' names, not their members.
Since the position of the "common" structure members are not consistent between the structures, the answer is no. Because of this, there is really no actual commonality between the structure.
With these structure it is hard (if not impossible) to write a single function that will handle them all. But, if you change these structure to share those common elements from another structure then it will be possible.
struct base
{
int common1;
char common2;
char *common3;
};
struct str1
{
struct base b;
long int aaaaaaaa;
};
struct str2
{
struct base b;
char bbbb;
};
struct str3
{
struct base b;
char ccccccccc[200];
int dddddddd;
int eeeeeeee;
};
Note: variable of struct base structure should be the first member of each struct, otherwise this technique won't work.
Now declare a function that take pointer to struct base.
void somefunc(struct base* var)
{
printf("%d %c %s\n", var->common1, var->common2, var->common3);
}
Usages:
struct str1 s1 = { 1, 'a', "sfad"};
struct str2 s2 = { 2, 'b', "sdfazx"};
struct str3 s3 = { 3, 'c', "oiurotu"};
somefunc((struct base*) &s1);
somefunc((struct base*) &s2);
somefunc((struct base*) &s3);
Can I somehow avoid code duplication and use a single generic function?
No. That sounds analogous to a C++ template, which of course C doesn't have and has no analog for, unless you include the preprocessor. C11 has _Generic, but that yields a kind of function overloading: one function per type, with preprocessor support to call them by a single name.
Function calls are to be decided at runtime
In C and C++, a function call -- the path of control -- is determined at compile time. There is no runtime "decision".
All the difference between the functions is the structs' names, not their members.
Actually, a key difference is in each struct's layout. The names are at different locations. The C compiler converts names to locations. After compilation, there are no names and no types, nothing to indicate that a location was named common1 or was part of a struct. There is only a reference to a memory location. It's up to you to use the language correctly, to ensure that reference is to a location you intended.
therefore a macro is irrelevant.
The preprocessor lets you manipulate names before the compiler converts them to numbers. If you want to do anything in C "by name", a macro is the only game in town.
In C89, if two or more structures start with members of matching types in matching order (they share a Common Initial Sequence) and both are part of the same union, any part of the Common Initial Sequence may be inspected using the appropriate named members of any type sharing the CIS. Your example doesn't use matching types, so it doesn't qualify, but if it were to use matching types in matching order, it would. So far as I can tell, C89 compilers through the 1990s unanimously applied the same principle with pointers to structures (so if structure types S1 and S2 have a CIS, a pointer of either type could be used to access members of the CIS). While the Standard didn't explicitly specify such treatment, the easiest way by far for a compiler to ensure that the rule would be applied in all cases involving unions was to make it apply in all cases with pointers as well, and many people (likely including the authors of the Standard) expected that compilers would naturally do so whether explicitly required or not.
C99 requires that if code is going to use a pointer of one structure type to
access a member of the CIS of another, a complete definition of the union type must be visible to let the compiler know of the potential aliasing between the types. Unfortunately, although this rule has a clear and obvious purpose (allowing programmers to exploit the CIS rule while allowing compilers to assume that accesses to totally unrelated structures won't alias) some compiler writers will assume that no pointer of a structure type will be used to access any other, even when a complete union type declaration containing both types is visible, and even in cases where the structures are, in fact, members of the same union object.
If you want to exploit the Common Initial Sequence rule, it may be necessary to use the -fno-strict-aliasing flag when using compilers that have one (even when not exploiting the CIS, using the flag may provide protection against compiler bugs). Code which exploits aliasing should endeavor to make it obvious to the compiler (e.g. by ensuring that a suitable union type is visible) but unless or until compiler writers start paying attention to such things, -fno-strict-aliasing will be necessary to accommodate their failure to do so.
Looks like I was wrong about restricting usage of the preprocessor:
#include <stdio.h>
struct str1
{
int common1;
char common2;
char *common3;
long int aaaaaaaa;
};
struct str2
{
char bbbb;
char *common3;
int common1;
char common2;
};
struct str3
{
char ccccccccc[200];
int common1;
char common2;
int dddddddd;
int eeeeeeee;
char *common3;
};
#define somefunc(var) \
printf("%d %c %s\n", var.common1, var.common2, var.common3);
int main()
{
struct str1 var1 = {1,'a',NULL, 4};
struct str2 var2 = {'b',NULL,2,'b'};
struct str3 var3;
var3.common1 = 3;
var3.common2 = 'c';
var3.common3 = NULL;
somefunc(var1);
somefunc(var2);
somefunc(var3);
}
output:
1 a (null)
2 b (null)
3 c (null)

Why does my program display the Array address instead of its contents?

My C program consists of an array called 'test_var'. It has another integer array 'arr_int' that consists of a set of integer numbers. My code looks something like this:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
int State(var);
int main()
{
int arr_int[3] ={1000, 1001, 1002, 1003};
int var;
int *test_var[4]={0};
State(var)
{
int i;
for(i=0; i<4; i++){
test_var[i] = arr_int[i];
i++;
}
return test_var[var];
}
printf("Enter a number between 0 and 3\n");
scanf("%d",&var);
State(var);
printf ("The array structure is %d", test_var[var]);
return 0;
}
However now when I try to print the returned value array test_var for the user input var=0 instead of the whole array(1000) I just get 0. What am I doing wrong here ? COuld somebody please tell me? Am I dereferencing the array in a wrong way?
EDIT : the code without the typo:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
int State(var);
int main()
{
int *arr_int[3] ={1000, 1001, 1002, 1003};
int var;
int *test_var[4]={0};
State(var)
{
int i;
for(i=0; i<4; i++){
test_var[i] = arr_int[i];
i++;
}
return test_var[var];
}
printf("Enter a number between 0 and 3\n");
scanf("%d",&var);
State(var);
printf ("The array structure is %d", test_var[var]);
return 0;
}
In your case,
the statement
test_var[i] = arr_int[i];
is wrong. test_var[i] is of type int *, and arr_int[i] is of type int, and they are not really compatible. To quote the standard, chapter §6.3.2.3
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
Then, you're using another statement like
printf ("The array structure is %d", test_var[var]);
%d expects an int argument, but you're supplying an int *. Pure undefined behaviour.
After that, int State(var) relies upon the older concept of default-to-int, which has been made invalid in C99 onwards.
In an array of 3 elements, you're supplying 4-member initializer list. Useless and confusing.
That said, FWIW, you're using a nested function, which is also not a part of standard C. It is supported as a GCC extension.
EDIT:
As per the comments, even if your arr_int is an array of of type int *, the initializers do not provide a seemingly valid value for the pointers to be dereferenced. That means, you cannot access the memory pointed to by those pointers, they are most likely to reside outside of the allocated memory area of your process and hence, invalid.
Nevertheless, for the point 2, mentioned earlier, the code is UB.
int arr_int[3] ={1000, 1001, 1002, 1003};
Array is of size 3 you initialize it with 4 elements.
Also the nested function is supposed to create a problem.They are supported as an extension in GNU C.
Note-Though you can declare a function inside of a function, but it's not a nested function.
EDIT
Your second code when you give input as 0 and 2 it seems to give correct output but when input is 1 or 3 it gives as 0. Surely it doesn't behave as intended.
int *arr_int[3] ={1000, 1001, 1002, 1003};
int *test_var[4]={0};
Why did you declare pointers instead of arrays? And why arr_int[3] is initialized with 4 integers?
It should be like this.
int arr_int[3] ={1000, 1001, 1002};
int test_var[4]={0}

Assigning a character array to a character array in a structure

I am working on a project that requires that I make an array of a certain structure type. The structure looks like this:
typedef struct
{
char array[30];
int num;
}structure
I have declared an array of these structures like this:
structure struct1[5];
I passed this structure array to a function which fills the first four elements with a string and a number. The fifth is left blank. Later in the program, I pass the array again and try to set the string in the structure to a user determined string using gets(). I am getting this error:
438:19: error: incompatible types when assigning to type 'char[30]' from type 'char *'
If I need to provide more clarification, please tell me.
Thanks!
EDIT: Here is what I am doing:
typedef struct
{
char array[30];
int num;
}structure;
void fillStructs(structure[]);
void userEditStructs(structure[]);
main()
{
structure myStructs[5];
fillStructs(myStructs);
userEditStructs(myStructs);
return 0;
}
void fillStructs(structure s[])
{
//code to fill myStructs elements 0-3.
}
void userEditStructs(structure s[])
{
char newArr[30];
int newNum;
printf("Please enter your string:\n\nEntry:\t");
gets(newArr);
printf("Please enter your number:\n\nEntry:\t");
scanf("%i", newNum);
s[5].array = newArr;
s[5].num = newNum;
}
you are doing something like this
char a[20];
a = "bla";
you cant do this.
do strcpy(a,"bla"); instead. ( #include <string.h> )
Without looking at the code you are probably trying to do something like:
struct[4].array = gets(<unknown>);
which won't work, as you can't assign the returned char* from gets to an array as the compiler says. You are also using gets, which is strongly discouraged as it performs no bounds checking. Instead, do the following:
fgets(struct[4].array, sizeof(struct[4].array), stdin);
which will do proper bounds checking.

Resources