Expression must have a constant value in C - c

int LCS_length(char* x, char* y)
{
int m = strlen(x);
int n = strlen(y);
char b[m + 1][n + 1];
char c[m + 1][n + 1];
}
In this code i want to declare a new two dimensional arrays, but my compiler write me this error:
Expression must have a constant value
Who knows what can i do, because a compiler don't let me do this statement in C language?
NOTE: it just part of the code and it has return statement later.

You must compile the code with a standard C compiler, such as gcc or clang etc. You can't compile using C++ compilers or non-C-compilers such as Microsoft VS.
Other than that, the code is fine apart from missing a return statement.
If you are stuck with old crap compilers, you can alternatively do an old style "mangled array":
size_t m = strlen(something) + 1;
size_t n = strlen(something) + 1;
...
char* b = malloc(m*n);
...
b[i*n + j] = something;
...
free(b);
That is how we used to allocate 2D arrays dynamically back in the old days.
Equivalent code using dynamic allocation in modern standard C would be:
char (*b)[n] = malloc( sizeof(char[m][n]));
...
b[i][j] = something;
...
free(b);

It looks that it wants a specific constant value like: char b[5][5];

Expression must have a constant value
C supports variable sized arrays from C99 standard. Maybe your compiler does not support Variable Length Arrays.
You can see more information at What's the point of VLA anyway?.
And may be helpful: Why aren't variable-length arrays part of the C++ standard?
You can use dynamically allocation instead (Unless you want each index to be a variable-length string, there is really no need for the char** trick: Correctly allocating multi-dimensional arrays):
char **b = malloc((m+1)*sizeof(char *));
if(b) {
for (int i = 0; i < m+1; i++0 {
b[i] = malloc(n+1);
if(!b[i]) {
// handle the error.
}
}
}
Or you can define the constant value MAX_ROW_LENGTH and MAX_COL_LENGTH:
#define MAX_ROW_LENGTH 100
#define MAX_COL_LENGTH 256
Then you can use:
char b[MAX_ROW_LENGTH][MAX_COL_LENGTH];

Related

How to return multiple types from a function in C?

I have a function in C which calculates the mean of an array. Within the same loop, I am creating an array of t values. My current function returns the mean value. How can I modify this to return the t array also?
/* function returning the mean of an array */
double getMean(int arr[], int size) {
int i;
printf("\n");
float mean;
double sum = 0;
float t[size];/* this is static allocation */
for (i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
//printf("%f\n",t[i]);
}
mean = sum/size;
return mean;
}
Thoughts:
Do I need to define a struct within the function? Does this work for type scalar and type array? Is there a cleaner way of doing this?
You can return only 1 object in a C function. So, if you can't choose, you'll have to make a structure to return your 2 values, something like :
typedef struct X{
double mean;
double *newArray;
} X;
BUT, in your case, you'll also need to dynamically allocate the t by using malloc otherwise, the returned array will be lost in stack.
Another way, would be to let the caller allocate the new array, and pass it to you as a pointer, this way, you will still return only the mean, and fill the given array with your computed values.
The most common approach for something like this is letting the caller provide storage for the values you want to return. You could just make t another parameter to your function for that:
double getMean(double *t, const int *arr, size_t size) {
double sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
}
return sum/size;
}
This snippet also improves on some other aspects:
Don't use float, especially not when you intend to return a double. float has very poor precision
Use size_t for object sizes. While int often works, size_t is guaranteed to hold any possible object size and is the safe choice
Don't mix output in functions calculating something (just a stylistic advice)
Declare variables close to where they are used first (another stylistic advice)
This is somewhat opinionated, but I changed your signature to make it explicit the function is passed pointers to arrays, not arrays. It's impossible to pass an array in C, therefore a parameter with an array type is automatically adjusted to the corresponding pointer type anyways.
As you don't intend to modify what arr points to, make it explicit by adding a const. This helps for example the compiler to catch errors if you accidentally attempt to modify this array.
You would call this code e.g. like this:
int numbers[] = {1, 2, 3, 4, 5};
double foo[5];
double mean = getMean(foo, numbers, 5);
instead of the magic number 5, you could write e.g. sizeof numbers / sizeof *numbers.
Another approach is to dynamically allocate the array with malloc() inside your function, but this requires the caller to free() it later. Which approach is more suitable depends on the rest of your program.
Following the advice suggested by #FelixPalmen is probably the best choice. But, if there is a maximum array size that can be expected, it is also possible to wrap arrays in a struct, without needing dynamic allocation. This allows code to create new structs without the need for deallocation.
A mean_array structure can be created in the get_mean() function, assigned the correct values, and returned to the calling function. The calling function only needs to provide a mean_array structure to receive the returned value.
#include <stdio.h>
#include <assert.h>
#define MAX_ARR 100
struct mean_array {
double mean;
double array[MAX_ARR];
size_t num_elems;
};
struct mean_array get_mean(int arr[], size_t arr_sz);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4, 5 };
struct mean_array result = get_mean(my_arr, sizeof my_arr / sizeof *my_arr);
printf("mean: %f\n", result.mean);
for (size_t i = 0; i < result.num_elems; i++) {
printf("%8.5f", result.array[i]);
}
putchar('\n');
return 0;
}
struct mean_array get_mean(int arr[], size_t arr_sz)
{
assert(arr_sz <= MAX_ARR);
struct mean_array res = { .num_elems = arr_sz };
double sum = 0;
for (size_t i = 0; i < arr_sz; i++) {
sum += arr[i];
res.array[i] = 10.5 * i / (128.0 - 1.0);
}
res.mean = sum / arr_sz;
return res;
}
Program output:
mean: 3.000000
0.00000 0.08268 0.16535 0.24803 0.33071
In answer to a couple of questions asked by OP in the comments:
size_t is the correct type to use for array indices, since it is guaranteed to be able to hold any array index. You can often get away with int instead; be careful with this, though, since accessing, or even forming a pointer to, the location one before the first element of an array leads to undefined behavior. In general, array indices should be non-negative. Further, size_t may be a wider type than int in some implementations; size_t is guaranteed to hold any array index, but there is no such guarantee for int.
Concerning the for loop syntax used here, e.g., for (size_t i = 0; i < sz; i++) {}: here i is declared with loop scope. That is, the lifetime of i ends when the loop body is exited. This has been possible since C99. It is good practice to limit variable scopes when possible. I default to this so that I must actively choose to make loop variables available outside of loop bodies.
If the loop-scoped variables or size_t types are causing compilation errors, I suspect that you may be compiling in C89 mode. Both of these features were introduced in C99.If you are using gcc, older versions (for example, gcc 4.x, I believe) default to C89. You can compile with gcc -std=c99 or gcc -std=c11 to use a more recent language standard. I would recommend at least enabling warnings with: gcc -std=c99 -Wall -Wextra to catch many problems at compilation time. If you are working in Windows, you may also have similar difficulties. As I understand it, MSVC is C89 compliant, but has limited support for later C language standards.

Macro with Parameters

In the code which follows, I keep getting an error. How to modify the third line? Why's that keep happening? What's wrong?
#include <stdio.h>
#include "stdlib.h"
#define ARRAY_IDX(type, array, i) ((type *)(array+i)) // you can only modify this line!
int main(int argc, const char * argv[]) {
void *ptr = malloc(10*sizeof(int));
#ifdef ARRAY_IDX
for (int i = 0; i < 10; i++) {
ARRAY_IDX(int, ptr, i) = i * 2;
}
for (int i = 0; i < 10; i++) {
printf("%d ", ARRAY_IDX(int, ptr, i));
}
free(ptr);
#else
printf("Implement ARRAY_IDX first");
#endif
}
Looking at
ARRAY_IDX(int, ptr, i) = i * 2;
and
printf("%d ", ARRAY_IDX(int, ptr, i));
shows that the expression
ARRAY_IDX(int, whatever, whatever)
should expand into an expression of type int (and an lvalue, so that we can assign to it).
Starting off with a void * you first need to change (cast) it to a pointer that allows indexing, and since you want to index the elements of that array (not its individual bytes, which would be a violation of aliasing) you need to make it an int * first:
(int *)(ptr)
Now you have a pointer to an integer (array, hopefully). Increment it:
(int *)(ptr) + (idx)
Finally, you need an lvalue int expression. Dereference the pointer to get that:
(*((int *)(ptr) + (idx)))
Converting that to a preprocessor macro is something that should be doable, so I leave it up to you.
Note that whoever is giving you that code is - IMHO - not a teacher you should trust. This won't teach you much about correct C. It might teach you something about the preprocessor. But don't write such code. Just don't. Use correct types if possible. Check for failure of malloc.
There is nothing wrong with adding an int to a void pointer. For many years, compiler designers assumed that this was standard behavior, and it was implemented as such. It's every bit as standard as anonymous structs and unions, which compilers have had for almost 20 years and were only recently added in C11. Practically all compilers will compile this just fine without any warnings or errors, and without having to use any special compiler flags.
Your problem is, as I have pointed out, that you are assigning a value to a pointer. You need to dereference it after the cast.
#define ARRAY_IDX(type, array, i) ((type *)array)[i]

How to use only part of an input array to a function?

I am required to pass a constant-size array to a function in C, but only use part of that array. Specifically, the following pseudo-code explains my situation:
void my_function(int arr_end,double arr[20]) {
Create new array arr_new that contains elements 0 to arr_end or arr
Use arr_new
}
So far, I tried to do the following:
void my_function(int arr_end,double arr[20]) {
double arr_new[arr_end+1];
int i;
for(i=0;i<=arr_end;i++){
arr_new[i] = arr[i];
}
// Now I can do what I want with arr_new
}
But I get the error: int arr_end expression must have a constant value
. Here's a screenshot of the error in Visual Studio Community 2015:
My problem is that arr_end is not constant (it means that at different times I want to extract a different portion of arr).
How can I achieve what I want (make arr_new contain a part of arr) using only for basic code and without malloc or anything like this? Thanks!
First in the my_function arguments you are declaring that you are receiving an array with a size of 20 (double arr[20]), since arrays cannot be passed by value it gets converted to double* arr (see this) without knowing how many elements arr has, so you should be carefully or you will get a segfault. A recommended approach would be to change double arr[20] to double* arr and add another argument for the size of arr. Example:
void my_function(const size_t arr_end, double* arr, const size_t arr_size) {
...
}
Second you are trying to use VLAs with MSVC which only supports C90 and VLAs we're added on C99 so you will need to allocate memory manually with malloc and free it with free when you finished using it.
Now here is the code fixed:
void my_function(size_t arr_end, double* arr, size_t arr_size) {
double* arr_new = NULL;
// Allocate enough memory to hold the array
arr_new = malloc((arr_end + 1) * sizeof(double));
// Copy arr elements to arr_new
for(int i = 0; i <= arr_end; i++){
arr_new[i] = arr[i];
}
// Now you can do what you want with arr_new
// When you finished using it.
free(arr_new);
}
Dynamic size arrays are not allowed in older c versions, so you can either:
change compilation flags to suit you and allow you to compile, if you are using an IDE this can be IDE dependent.
allocate the array dynamically using malloc or a similar function like so:
void my_function(int arr_end,double arr[20])
{
double *arr_new = malloc((arr_end+1) * sizeof(arr[0]));
int i;
for(i=0;i<=arr_end;i++){
// do whatever you need
}
}
allocate an array of size 20 on the stack and just use only part of it(using the for loop) like so:
void my_function(int arr_end,double arr[20]) {
double arr_new[20];
int i;
for(i=0;i<=arr_end;i++){
//do whatever you need
}
}
if you must send only the parts you need, method 2 is preferable.
As far as I know the problem is that when you are creating dynamic arrays then
the only way is using malloc to allocate space. Then you assign it to an array
as in double arr_new[arr_end+1];. arr_end can only be an explicit value, e.g., 1, 2, or 3, not a variable like arr_end. It should be something like this double arr_new[5];
Apparently, the problem lies with Visual Studio. The concept of Variable Length Arrays (VLAs) is of the C99 standard, whereas Visual Studio seems to support only C90.
They do seem have a workaround for that however, you can find it here: https://msdn.microsoft.com/en-us/library/zb1574zs(v=vs.140).aspx
Use dynamic allocation. Code:
void foo(int end, double arr[20]){
double* newArr = malloc((end + 1) * sizeof(double));
//now you can use newArr like a normal array
//Copy like this
for(int i = 0; i < end; i++){
newArr[i] = arr[i];
}
}

Deferencing Void Pointer / Void Pointer Copy

Platform: Linux 3.2.0 x86 (Debian Wheezy)
Compiler: GCC 4.7.2 (Debian 4.7.2-5)
I am writing a function that copies the contents of a buffer to another buffer. I use a void pointer so that the function is not type specific. I have a testable version and it appears that the function is working properly. But I do not know if what I am doing is legal so my question is what are the pitfalls of what I have done if there are any.
#include <stdio.h>
#include <stdlib.h>
void* voidcpy(void *void_ptr, size_t nbytes)
{
char *char_ptr = void_ptr;
char *cpy_char_ptr = NULL;
size_t i = 0;
if((cpy_char_ptr = malloc(nbytes)) == NULL) return NULL;
for(; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
return cpy_char_ptr;
}
int main()
{
short int *intp = NULL;
short int *cpy_intp = NULL;
size_t siz = 5;
int i = 0;
if((intp = malloc(siz * sizeof(short int))) == NULL)
{
perror("(malloc)");
return -1;
}
intp[0] = 0;
intp[1] = 14;
intp[2] = 187;
intp[3] = 12678;
intp[4] = -234;
if((cpy_intp = voidcpy(intp, siz * sizeof(short int))) == NULL)
return -2;
printf("intp = %p\ncpy_intp = %p\n\n", (void*)intp, (void*)cpy_intp);
for(; i < siz; i++) printf("cpy_intp = %i\n", cpy_intp[i]);
free(intp);
free(cpy_intp);
return 0;
}
Yes, this is perfectly legal, in C you can legally assign a void pointer to any other pointer type and you can assign any pointer type to a void pointer.
In C++ this is not allowed. In C++ you would have to use a reinterpret_cast to cast to a different pointer type because the free void pointer casting that is allowed in C is considered a "loop hole" that is easy to make mistakes with.
Of course there is a truth to that idea, if you're not careful you could be doing the wrong thing, e.g. you could easily pass a pointer to a pointer to this function by mistake and then your function will happily overwrite whatever is on the stack beyond that pointer. This is no fault of your implementation however, it's just the way the function is to be used and memcpy behaves no differently.
Nevertheless you would be better off using memcpy instead as this will very likely be much better optimized, though these days the compiler will probably make a pretty decent version out of your code as well.
A few more pointers;
1) you do not need to malloc the original array, you can initialize it statically like so
short int int_arr[] = {
0,
14,
187,
12678,
-234,
};
2) you can then call your function in the following way:
cpy_int_arr = voidcpy(int_arr, sizeof(int_arr));
3) if you don't want to define the array statically, then use the pointer to get the element size, that way you can change the array type without needing to change it somewhere else in the code, which reduces the potential dangers of the "loop hole" void casting:
cpy_intp = voidcpy(intp, siz * sizeof(*intp));
4) you don't need to cast to void* in the printf call
5) try to assign variables immediately and do not put assignments inside of if statements:
char *cpy_char_ptr = malloc(nbytes)
if (cpy_char_ptr == NULL)
return NULL;
6) similarly you can define a iteration variable inside the loop clause:
for(size_t i = 0; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
The reason to define variables as late as possible and initialize them immediately is that you keep the scope of the variables as small as possible and you can not mistakenly use a variable before it is initialized.
7) (personal preference) don't use type names in your identifiers (intp, voidcpy) your code will either become difficult to read/understand if your identifier states a type different from what the variable actually is, (e.g. your type is actually a short int and not an int as the variable name would suggest,) or you will need to change the identifier throughout the entire code whenever you change the type with the possibility of making mistakes.

Why is not the last column of my matrix printed?

I have a 2x3 char matrix stored in column major order (yes I know that this is a little confusing, but please bear with me), as a multidimensional char[3][2] array (notice the switch of indices). Now, I want to print this matrix. However, for some reason the last column is not printed. Why is that?
Here's my code:
#include <stdio.h>
#define ARRAY_SIZE(x) ((sizeof (x)) / (sizeof((x)[0])))
typedef char matrix[3][2];
void print_matrix(matrix a)
{
for (size_t i = 0; i < ARRAY_SIZE(a[0]); i++) {
printf("[");
for (size_t j = 0; j < ARRAY_SIZE(a); j++) {
printf(" %c", a[j][i]);
}
printf(" ]\n");
}
}
int main(int argc, char *argv[])
{
matrix a = {{'a','b'},{'c','d'},{'e','f'}};
printf("sizeof(a) = %zu\n", ARRAY_SIZE(a));
printf("sizeof(a[0]) = %zu\n", ARRAY_SIZE(a[0]));
print_matrix(a);
return 0;
}
Compiling and running gives me this:
$ gcc -Wall -std=c99 foo.c; ./a.out
sizeof(a) = 3
sizeof(a[0]) = 2
[ a c ]
[ b d ]
Expected output:
[ a c e ]
[ b d f ]
It's because your function is effectively:
void print_matrix(char a[3][2])
but this is really:
void print_matrix(char (*a)[2])
So your macro produces the wrong result using sizeof (you're calculating the size of a pointer, and the size of a two element char array). If you pass in the two values to the function as parameters and use those in the loop, it should work.
Add:
printf("ARRAY_SIZE(a) = %zu\n", ARRAY_SIZE(a));
printf("ARRAY_SIZE(a[0]) = %zu\n", ARRAY_SIZE(a[0]));
to print_matrix and you will see the problem:
ARRAY_SIZE(a) = 2
ARRAY_SIZE(a[0]) = 2
You have been bitten by one of the bizarre corner cases of C. Multidimensional arrays are not as fully supported as they seem to be. In particular, passing them as arguments to functions doesn't create quite the data type that you're expecting, and therefore the ARRAY_SIZE macro doesn't work properly on the function argument.
What's actually going on under the hood is weird, and I'm not sure I understand it well enough to really explain it, but the brief version is that arrays as function parameters degrade into pointers. So the function parameter char a[3][2] actually becomes something vaguely equivalent to char *a[2].
the sizeof operator doesn't work because arrays sent as parameters get converted to pointers and DECAYING of the pointer takes place! so inside the function you can't know the sizeof the matrix.

Resources