Can I use labels as index in C global data table? - c

I have a large global array in which I keep changing some of the values which when compiled for different purposes requires the table to be altered. Basically the table as a core structure and based on different purposes additional values may get added/removed from it.
The values are somewhat like:
int global_array[] =
{
...
6, 6, 78, 9,
12,
13,5
19,
47, 768, 98, 89
...
};
I need to access some of core structure values (lets say "12" here) inside these table. So while compiling for different purposes, index of concerned value ("12") changes. For same reason I cannot keep this table as structure. Keep in mind this is a huge table and for some reason we don't write values in uniform fashion (read linear).
So for every new purpose I have to manually count index of value "12" which is tedious. I want a future proof process.
I was wondering if I could use something like:
int global_array[] =
{
...
6, 6, 78, 9,
INDEX: 12,
13,5
19,
47, 768, 98, 89
...
};
And access/modify values at run-time as below:
*(uint8 *)INDEX = 20;

You can keep additional pointer variables around that point to specific entries. Whenever needed, you can adjust the array entry the pointer points to.
Example:
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
int *idx = &global[0];
int main() {
*idx = 20;
printf("%d\n", *idx);
return 0;
}
Alternatively, you could use a preprocessor macro (if the location that is referred to is known at compile time and will not change):
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
#define INDEX (global[0])
int main() {
INDEX = 20;
printf("%d\n", INDEX);
return 0;
}
Given you only need to do this once at program start, maybe you just need a function that does the counting for you.
Example:
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
int find_index(int value, int *array, size_t size) {
for (int i = 0; i < size; i++)
if (array[i] == value)
return i;
return -1;
}
int main() {
int value = 4;
int index = find_index(value, global, sizeof(global)/sizeof(*global));
printf("index of %d: %d\n", value, index);
return 0;
}
Here's the output:
$ gcc tt.c -std=c99 && ./a.out
index of 4: 3
If the positions of lots of entries needs to be tracked throughout the entire runtime of the application you should consider using a key-value storage (e.g., a binary search tree) to keep track of the values' indices. You should then use special methods that encapsulate the update and retrieval operations that will also adjust the indices stored in that "index" data structure.

From ISO/IEC9899:
6.8.6.1 The goto statement
Constraints
1 The identifier in a goto statement shall name a label located somewhere in the enclosing function.
A goto statement shall not jump from outside the scope of an identifier having
a variably modified type to inside the scope of that identifier.
As a global aray is not located in an enclosed function, this is not allowed!

C does not provide any syntax to do what you want.
One way to solve this so you don't have to count something with each change, is to have a tool of yours do the counting. After all, machines are good at counting things. For example, you could mark the interesting postitions in the initializer with a special comment, i.e.
int global_array[] =
{
6, 6, 78, 9,
12, /* INDEX12 */
13,5,
19,
47, 768, 98, 89
...
};
The index for the array element is then found by counting the commas from the start of the declaration, minus one. Turn the result into a compile-time macro with -DINDEX12=42, et voilà! All you need is an idea of where the declaration starts (putting it in a separate header file is the easy route), and run for example
$ awk '/global_array/,/INDEX12/ { commas += gsub(/,/, ",") }
END {print "-DINDEX12=" commas - 1}' file.h
-DINDEX12=4
This is easily extended to deal with any number of INDEXNNN macros. Beware of the potential off-by-one for the last array initializer (which doesn't have a comma in your snippet, but C does allow it...)
Placing this preprocessing in a snugly Makefile left as an exercise.

Related

In C, how do I print the index of however many values the user chooses to input?

I am essentially attempting to print out how many values are entered for the array in this code (If they enter 10 numbers, I would want to print for index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 as well as taking user inputs for the array values and printing those in a table-like fashion beside of their index). How would I go about doing this, and is there anything wrong with this code?
#include <stdio.h>
#include <stdlib.h>
int arr_1 (int ar[], int size);
int main()
{
double sentinel[20];
printf("Hello User!\n\nEnter up to 20 values, and type -1 when you are finished: ");
for (int i = 0; i < 20; ++i) {
scanf("%lf", &sentinel[i]);
}
for (int i = 0; i < 20; ++i) {
printf("%f\n", sentinel[i]);
}
printf("\n%lu\n", sizeof(sentinel[20]));
}
int arr_1 (int ar[], int size)
{
return 0;
}
First, you will need to check whether the user actually inputs as many values as you expect to get (20 in your case). The scanf() function tells you, in its return value, whether it actually managed to parse another number from the input.
Then, you'll need to exit your loop when no more numbers are available on the input.
Finally, you'll need to keep track of how far you got in the loop. One way to do this is to define the loop index (i) in the scope outside the loop. That way it's not lost to you when the loop is eventually cleared.
Once you have the last i value (suppose you assign it to a new variable like so, int num_input_elements = i + 1) then you know your indices are 0, 1,... num_input_elements - 1. And you can easily loop through those, printing, in fact, your loop index.
Additional notes:
Don't use the "magic number" 20 all over. Use a preprocessor definition before you first use it, e.g. something like #define MAX_NUM_ELEMENTS 20.
sentinel is a confusing name for your array, because a sentinel typically means something else in programming.
sizeof(sentinel[20]) is always sizeof(double)... not the number of elements you got on the input.

Determine positions in array at compile-time in c

Is there a way to determine a position within a const array at compile-time in c? Here's an example of what I'm trying to do:
const unsigned char DATA[] = {
// Part 1
// hundreds or thousands of values
// Part 2
// compiler records this position in the array in PART2
// hundreds or thousands of values
// Part 3
// compiler records this position in the array in PART3
// hundreds or thousands of values
// ...
};
const unsigned int PART_IDX [] = {
// index to Part 1
0,
// index to Part 2
PART2,
// index to Part 3
PART3,
// ...
};
I could calculate the indexes at run-time, but would rather have them already done, since the array is constant. I could make a program that analyzes the source code, counts the number of elements in each part, and inserts the data in PART_IDX, but I would really like to have the compiler do this at compile-time. That way if data gets inserted or deleted, or parts get added or removed, the compiler still generates correct code. Does someone know how I could do this? Thanks!
Edit:
To clarify, using a example with actual data:
const unsigned char DATA[] = {
// Part 1
0, 1, 2, 3, 4,
// Part 2
// compiler records this position in the array in PART2 (should be 5)
10, 11, 12, 13, 14, 15, 16,
// Part 3
// compiler records this position in the array in PART3 (should be 12)
20, 21, 22
};
const unsigned int PART_IDX [] = {
// index to Part 1
0,
// index to Part 2
PART2, // should be 5, points to 10 in the array
// index to Part 3
PART3, // should be 12, points to 20 in the array
};
Question is, what can I put in place of the lines that start with // compiler records this position ... to get the compiler to record the appropriate values in PART2 and PART3?
Rather than trying to kludge C to do something it was not meant to do, a better and common method is to prepare data for a C program by writing a program that prepares the data. That is, write some other program that counts the data in the parts and writes the C code necessary to initialize both DATA and PART_IDX.
Another option is:
Put all the data each part in a separate “.h” file, such as files “part1.h”, “part2.h”, “part3.h”.
To initialize DATA, include all of those header files in its initializer list.
To calculate the indices for the parts, use sizeof to calculate the numbers of elements in proxy arrays containing the preceding parts.
Example:
“part1.h” contains 10, 11, 12,.
“part2.h“ contains 20, 21,.
“part3.h” contains 30, 31, 32, 33,.
The C file is:
const unsigned char DATA[] =
{
#include "part1.h"
#include "part2.h"
#include "part3.h"
};
const unsigned int PART_IDX [] =
{
0,
sizeof (const unsigned char []) {
#include "part1.h"
} / sizeof (const unsigned char),
sizeof (const unsigned char []) {
#include "part1.h"
#include "part2.h"
} / sizeof (const unsigned char),
};
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 3; ++i)
printf("Part %d begins at index %d with value %d.\n",
i, PART_IDX[i], DATA[PART_IDX[i]]);
}
Is there a way to determine a position within a const array at compile-time in c?
Yes. Remember that C source files can be generated, and improve your build automation accordingly (e.g. edit your Makefile).
So just generate the second part (e.g. with some awk or Guile script on Linux, or your own simple meta-program coded in C -or some scripting language- that output portions of generated C code). Play with preprocessor tricks. See this answer for inspiration.
You could, assuming you use GCC as your C compiler, also consider writing your ad-hoc GCC plugin, but in your particular case it is not worth the effort.
BTW, my Bismon program uses such meta-programming tricks. And GCC itself has dozens of ad-hoc code generators.
If you generate some complex enough C code, I recommend keeping internally some kind of AST of it.

Printing last element in an array using if statement

I am currently trying to learn about using pointers and functions together in C, which I don't think is easy.
I am trying to print the last element in an array, it actually does the opposite and prints the first element.
I know people normally use for loops, but I can't figure out how to do that with exactly this kind of problem and therefore I thought that I would try it out with an if statement instead.
Edit:
Why is if statement not working in this case? It seems logic that it should work...
My main.c file:
#include <stdio.h>
#include <stdlib.h>
#include "functions.h"
#define Size 7
int main(void)
{
int array1[] = { 11, 88, 5, 9, 447, 8, 68, 4 };
maxValue(array1, Size);
return 0;
}
My functions.h file:
#pragma once
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
int maxValue(const int *, int);
#endif
My functions.c file:
#include "functions.h"
#include <stdio.h>
#include <stdlib.h>
int maxValue(const int *array1, int Size)
{
int max = array1[0];
if (max < array1[Size]) {
Size++;
max = array1[Size];
}
printf("Max value: %d \n", max);
}
Why is if statement not working in this case? It seems logic that it should work...? Because here
if (max < array1[Size]) { }
Size is defined as 7 and you are comparing array1[0] with array1[7] i.e 11 < 4 -> false, hence it doesn't enter into if block, so the last printf executes and that prints max. But its not a correct logic if if blocks becomes true then further Size++ will cause accessing out of bound array elements which cause undefined behavior.
int maxValue(const int *array1, int Size)
{
int max = array1[0];
if (max < array1[Size]) { /* 11 < 4 false, skips if block */
//Size++; /* this is wrong as Size++ here and next accessing array1[Size] cause UB due to accessing out of bound array element */
max = array1[Size];
}
printf("Max value: %d \n", max); /* max is stills array1[0] i.e 11 */
}
Let's simulate what the CPU does when it enters the maxValue function with those arguments. 1. The variable max is assigned the value of array1[0], which is 11.
2. If max (11) is less than array1[7] (4). It is not, so the if block is not executed.
3. Print max: print 11.
Another thing: Your program causes undefined behaviour. Let's take an example where array1[0] is 3, instead of 11. The if block will be executed (3 < 4), so:
Size is incremented to 8.
max is assigned array1[8]. Since the last index in array1 is 7 (that is how you declared the array), you are accessing a memory adress which you are not supposed to access. This is undefined behaviour.
The names maxValue() and max are misleading and confusing what you are trying to do. lastValue() and last would make much more sense.
However what you are trying to do makes no sense in C because arrays are of known length, so you can access the last element directly:
int array1[] = { 11, 88, 5, 9, 447, 8, 68, 4 };
int array_length = sizeof(array1) / sizeof(*array1) ;
printf("Lastvalue: %d \n", array1[array_length - 1] ) ;
However you cannot do this in a function because arrays are not first class data types in C and when passed to a function will "degrade" to a simple pointer without any information regarding the size of the array pointed to. The calling function having the size information must pass that too (as you have done, but then appeared to get very confused):
void printLast( int* array, int length )
{
printf( "Lastvalue: %d \n", array1[length - 1] ) ;
}
It is difficult to see why you thought you might need any other code or what your maxValue() function is intended to achieve. The "logic" which you say "should work" is thus:
If value of the first array element is less than the value of the last array element, then print the undefined value one past the end of the array; otherwise print the first element of the array.
If you wanted to print the last element, then you simply print it, the value of the first element has nothing to do do with it. Either way you should not index past the end of the array - that value is undefined.

Is there a concise way (without loops) to create a linearly spaced array in C?

I'd like to create an array of numbers, 80 to 86, separated by increments of 0.5. I know I can create an array to represent this by writing
float Vector1[] = {80, 80.5, 81, 81.5, 82, 82.5, 83, 83.5, 84, 84.5, 85, 85.5, 86};
In Matlab, which is what I normally use, this is simply
Vector1 = 80:0.5:86;
In this particular case, it's not a big deal to write the array manually, but for a larger array it wouldn't be feasible to write out every entry. Is there similar functionality in C to create linearly spaced one-dimensional arrays of arbitrary bounds and step size? As stated in the title, I'd like to know if there's a solution that doesn't involve using a loop.
You could write a separate piece of code that generates the static declaration:
makevector.c:
#include <stdio.h>
int main()
{
float i;
int first = 1;
printf("float Vector1[] = { ");
for (i = 80; i <= 86; i += 0.5) {
if (first) {
first = 0;
} else {
printf(", ");
}
printf("%.1f", i);
}
printf(" };\n");
return 0;
}
Then run it:
gcc -o makevector makevector.c
./makevector > vector.c
While technically you still have a loop, it's done ahead of time to create code so that you don't need a loop in your real code.
No it is not possible without loops.All languages which offer functionality that you have asked uses a loop to achieve it.In C you just have to write your own.

Is it possible to use an array within a for loop?

This my code as it stands:
int sliderNum; // Variable Declaration //
// Loop Sequencer //
for (sliderNum = 41; sliderNum <= 48; sliderNum = sliderNum + 1)
However I need to change this so the loop no longer counts from 41-48 but instead counts e.g 73,71,34,46,52,4,17 etc. So a specific set of numbers one after another but not like counting normally.....hope that makes sense.
As you can probably tell, I'm pretty new to this programming stuff so any help would be greatly appreciated.
Cheers.
int a[] = {1,4,7,10};
for(int i=0; i<sizeof(a)/sizeof(a[0]); ++i)
{
....process a[i]
}
I recommend consulting a good book on c.
Regarding the code: This is basically looping over an array with iterations = size in bytes of the array / size in bytes of an element of array
You might even place the array literally within the for loop definion. This way, it somewhat resembles "with" statement, that is common in Python:
#define ARRAY_LEN(a) (sizeof(a)/sizeof(*a))
int main()
{
for (int a[] = {73, 71, 34, 46, 52, 4, 17}, i = 0; i < ARRAY_LEN(a); i++) {
// ...
}
}
Personally, I wouldn't write such code on production, as it may be questioned as "too clever", whereas putting the array at the top of loop seems to make it more readable.

Resources