I am mindblown by this small code:
#include <stdio.h>
int main()
{
int limit = 0;
scanf("%d", &limit);
int y[limit];
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
return 0;
}
How on earth this program is not segment-faulting as limit (size of the array) is assigned at runtime only?
Anything recently changed in C? This code shouldn't work in my understanding.
int y[limit]; is a Variable Length Array (or VLA for short) and was added in C99. If supported, it allocates the array on the stack (on systems having a stack). It's similar to using the machine- and compiler-dependent alloca function (which is called _alloca in MSVC):
Example:
#include <alloca.h>
#include <stdio.h>
int main()
{
int limit = 0;
if(scanf("%d", &limit) != 1 || limit < 1) return 1;
int* y = alloca(limit * sizeof *y); // instead of a VLA
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
} // the memory allocated by alloca is here free'd automatically
Note that VLA:s are optional since C11, so not all C compilers support it. MSVC for example does not.
This doesnt compile in visual studio because limit "Error C2131 expression did not evaluate to a constant"
If you make limit a constexpr though then the compiler will not mind because youre telling it it wont change. You cant use 0 though as setting an array to a constant size length zero is nonsence.
What compiler does this run on for you ?
Related
I just have a function that finds out the maximum value of an array of integers, but I get a segmentation fault, which I can't find because the compiler doesn't show me the line of the error.
This is my C code:
#include <stdlib.h>
#include <stdio.h>
//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int **arrayPointer){
int max = 0;
for (int i = 0; i < 3; i++) {
if (*arrayPointer[i]>max) {
max = *arrayPointer[i];
}
}
return max;
}
int main (int argc, char **argv) {
int array[4]={1,2,3,4};
int *ptr = array;
int z = groesstesElement(&ptr);
printf("%d\n", z);
return EXIT_SUCCESS;
}
I use macOS and VSC.
In C, array indexing [] has higher precedence than pointer de-referencing *: https://en.cppreference.com/w/c/language/operator_precedence
Some parentheses fix the segfault.
if ((*arrayPointer)[i]>max) {
max = (*arrayPointer)[i];
}
Due to the operators precedence, with
*arrayPointer[i]
you are telling your program:
Take the i-th element of the array arrayPointer and dereference it.
But arrayPointer is a pointer to int *, so all you get is the address of ptr (the int ** pointer defined from main) with an offset. When you finally dereference it you are likely accessing an invalid address, causing segmentation fault.
As already suggested by the main answer, the fix is done using parenthesis in order to apply the operators in the order you want:
(*arrayPointer)[i]
Secondary issues in the code
Even though with the correction above the program won't crash anymore, it won't work. Searching through the array with the loop
for (i = 0; i < 3; i++)
you won't include the last item in the search (index 3), skipping precisely the index that, in your example, contains the maximum value. You probably meant for (i = 0; i < 4; i++) or for (i = 0; i <= 3; i++).
Anyway, using magic numbers in the code (in this case the dimension of the array) is considered bad practice. A better solution would have been using a #define, but an even better solution would have been passing to the function the size of the array:
#include <stdlib.h>
#include <stdio.h>
#define ARR_SIZE 4
//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int *arrayPointer, unsigned int arrSize){
int max = 0, i;
for (i = 0; i < arrSize; i++) {
if (arrayPointer[i]>max) {
max = arrayPointer[i];
}
}
return max;
}
int main (int argc, char **argv) {
int array[ARR_SIZE]={1,2,3,4};
int z = groesstesElement(array, ARR_SIZE);
printf("%d\n", z);
return EXIT_SUCCESS;
}
Please note how there's no need to use a double pointer anymore.
I need your help, becouse I dont know whether I realy free the allocated memory. I also will be very grateful, if you could advice me some tools for this purpose. Thanks!
P.S You can skip bb_sort and swap functions.
#include <stdio.h>
#include <stdlib.h>
typedef struct DArray{
double * array;
int size;
} DArray;
void getArrays(DArray * arrays, int numOfArrays){
int curArraySize, i;
while(numOfArrays >= 0){
printf("Input size of array: "); scanf("%d", &curArraySize);
if(arrays[numOfArrays].array = (double*)malloc((arrays[numOfArrays].size = curArraySize)*sizeof(double))){
for(i = 0; i < arrays[numOfArrays].size; ++i)
arrays[numOfArrays].array[i] = rand()%100;
--numOfArrays;
}
else{
printf("Error, have no enough memory in the system!"); break;
}
}
}
void swap(double * arr, int pos1, int pos2) {
int tmp = arr[pos1];
arr[pos1]=arr[pos2];
arr[pos2]=tmp;
}
double * bb_sort(double * arr, int size){
int i, j, noChanges = 1;
while(1){
for(i = 0;i < size;++i){
for(j = 0;j < size-1;++j){
if(arr[j] < arr[j+1]){
swap(arr, j, j+1);
noChanges = 0;
}
}
if(noChanges) return arr;
noChanges = 1;
}
}
}
int main() {
srand (time (NULL));
int numOfArrays, i, j;
printf("Input number of arrays: "); scanf("%d", &numOfArrays);
DArray arrays[numOfArrays];
getArrays(arrays ,numOfArrays-1);
for(i = 0; i < numOfArrays; ++i){
bb_sort(arrays[i].array, arrays[i].size);
}
for(i = numOfArrays-1; i >= 0; --i){
printf("\nSorted array num#%d\n", i+1);
for(j = 0; j < arrays[i].size; ++j)
printf(" %.1lf ", arrays[i].array[j]);
free(arrays[i].array); <------FREE MEMORY?
printf("\n");
}
printf("Done!");
while(1){
}
return 0;
}
=====================================================================================================
Short Answer:
The OP ask if 'memory is cleaned'. Technically, there is no requirement for the free implementation to CLEAN the memory (e.g, sets the data to zero, or some random data). Most implementation will not CLEAR to memory to save time.
If, by mistake, the code will try to read the data, it will usually find the data is still in memory, potentially modified by the free call, or by other code, which was assigned the freed memory to other tasks.
For security sensitive information (password, credit card numbers, private keys), it is common to ZERO the data, or to fill the region with other pattern, before calling free. It will make it harder/reduce the risk of the data being access by mistakes, bugs or hacking.
Some memory debuggers will fill freed memory with pattern data/guards/etc, to help detect memory problems earlier than later.
Yes it will, since your program created array pointer using malloc function, and it does not manipulate that pointer, according to C99 standard (ISO/IEC 9899:1999):
7.20.3.2 The free function (p: 313):
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Code:
#include <stdio.h>
int main() {
int size;
scanf("%d", &size);
int foo[size];
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
return 0;
}
How does this code compile? More specifically: how does the compiler know what is the size of frame main if size of local variable foois not known at compile time. I was expecting a compile error along the lines: "foo has incomplete type"
To have also tried the code and it also runs fine:
In your code, you will first read data to specify size of array elements and then it will allocate that array on stack.
This approach is available from C99.
How compiler knows the size? It doesn't know. if you will enter too big value for size you may get stack overflow.
It will compile in a way that it will make sure to create as big push as required to put entire array to stack according to variable of size multiplied by size of single array element:
stack_size_usage = size * sizeof (int)
In C89, this would reproduce error as all variables must be first initialized before any code can be executed.
I would instead use HEAP memory for this type of allocation.
#include <stdio.h>
int main() {
int size;
int* foo;
scanf("%d", &size);
foo = malloc(sizeof(*foo) * size);
if (!foo) { /* failed, stop program */ }
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
free(foo);
return 0;
}
I am trying to find out the Lagrange's Interpolation with the program. I have solved it using arrays but when using dynamic memory allocation, the program is giving me garbage result.
#include<stdio.h>
#include<conio.h>
#define SIZE 100
int main()
{
float *x,*y;
float value = 0,ask,temp;
int i,j,n;
printf("Enter size");
scanf("%d",&n);
x = (float*)malloc(n*sizeof(float));
y = (float*)malloc(n*sizeof(float));
for(i = 0; i < n;i++)
{
printf("x[%d]: ",i);
scanf("%f",(x+i));
printf("y[%d]: ",i);
scanf("%f",(y+i));
}
printf("Enter value to find");
scanf("%f",&ask); //cin >> ask;
for(i = 0; i < n;i++)
{
temp = 1;
for(j = 0; j < n; j++)
{
if(i != j)
{
temp = temp * (ask-(*(x+i))/(*(x+i)-*(x+j)));
}
}
value = value + temp * *(y+i);
}
printf("%f",value);
}
You need to #include <stdlib.h>, since that is the header that declares functions that perform dynamic memory allocation (malloc(), etc).
You will find, assuming you use a C compiler and not a C++ compiler, that the type conversions on the malloc() calls are not required.
x = (float*)malloc(n*sizeof(float)); /* (float *) is unnecessary */
The problem is that, without stdlib.h, the compiler assumes malloc() returns an int. The type conversion might allow the code to compile without stdlib.h, but the result is subsequent usage of the malloc()d pointer will have undefined behaviour, since the pointer does not necessarily survive the round trip (being converted to int and then back).
If you are using a C++ compiler, then the (float *) type conversion AND #include <stdlib.h> are BOTH required to avoid undefined behaviour.
Please have a look at the following code and tell me where does ***ptr locates ?
i.e. i have a feelings that ***ptr actually locates at ptr[0][0][0]
Am I wrong ? The following is a 3d representation of pointer. where I am trying to assign some characters and later i wanted to test what is the index of ***ptr? will be waiting
#include<stdio.h>
#include<conio.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int i,j,k;
void main()
{
clrscr();
ptr=(char *)malloc(row*sizeof(char *));
for(i=0;i<row;i++)
{
*(ptr+row)=(char *)malloc(rw*sizeof(char *));
printf("\t:\n");
for(j=0;j<rw;j++)
{
*(*(ptr+row)+rw)=(char *)malloc(col*sizeof(char *));
if(i==0 && j==0)
{ // *(*(ptr+row)+rw)="kabul";
**ptr="zzz";
}
else
*(*(ptr+row)+rw)="abul";
printf("\taddress=%d %d%d = %s\n",((ptr+row)+rw),i,j,*(*(ptr+row)+rw));
}
printf("\n");
}
printf("%c %d",***ptr,ptr);
getch();
}
First of all, I find your coding style extremely hard to read.
Answering your question, yes, ptr[0][0][0] is a synonym of ***ptr. Thats because a[b] is by definition equal to *(a+b), so ptr[0] is equal to *ptr, etc.
Said that, here is my version of your code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int main()
{
int i, j;
ptr = (char***)malloc(row * sizeof(char **));
for(i = 0; i < row; i++)
{
ptr[i]= (char**)malloc(rw * sizeof(char *));
printf("\t:\n");
for(j = 0; j < rw; j++)
{
ptr[i][j] = (char*)malloc(col * sizeof(char));
if (i == 0 && j == 0)
{
strcpy(ptr[i][j], "zzz");
}
else
{
strcpy(ptr[i][j], "abul");
}
printf("\taddress=%p %d,%d = %s\n", ptr[i][j], i, j, ptr[i][j]);
}
printf("\n");
}
return;
}
Note the following changes:
Never write void main in C or C++. And throw away any book that prints it.
The argument of malloc is usually the number of elements times the size of the element. Place special attention to the real type that you intend to use.
The return of malloc is usually cast to the type pointer-to-the-type-of-the-element.
The index in the arrays should be i and j, not row and rw.
Why all the *(ptr + x) stuff? That's why we have the ptr[x] syntax.
You probably want to use strcpy to fill your strings, but difficult to say without explaining the problem.
When you want to printf a pointer, use %p.
If you use malloc, include <stdlib.h>.
Prefer local variables (i, j) to global ones, particularly for loops.
And a few other minor changes here and there...
PS. <conio.h>? Really? Are you still using Turbo-C or what?