This program worked fine when i manually iterated over 5 individual variables but when I substituted them for those arrays and for loop, I started getting floating point exceptions. I have tried debugging but i can't find were the error comes out from.
#include <stdio.h>
int main(void) {
long int secIns;
int multiplicadors[4] = {60, 60, 24, 7};
int variables[5];
int i;
printf("insereix un aquantitat entera de segons: \n");
scanf("%ld", &secIns);
variables[0] = secIns;
for (i = 1; i < sizeof variables; i++) {
variables[i] = variables[i - 1]/multiplicadors[i - 1];
variables[i - 1] -= variables[i]*multiplicadors[i - 1];
}
printf("\n%ld segons són %d setmanes %d dies %d hores %d minuts %d segons\n", secIns, variables[4], variables[3], variables[2], variables[1], variables[0]);
return 0;
}
The problem is you're iterating past the ends of your arrays. The reason is that your sizeof expression isn't what you want. sizeof returns the size in bytes, not the number of elements.
To fix it, change the loop to:
for (i = 1; i < sizeof(variables)/sizeof(*variables); i++) {
On an unrelated note, you might consider changing secIns from long int to int, since it's being assigned to an element of an int array, so the added precision isn't really helping.
Consider this line of code:
for (i = 1; i < sizeof variables; i++) {
sizeof isn't doing what you think it's doing. You've declared an array of 5 ints. In this case, ints are 32-bit, which means they each use 4 bytes of memory. If you print the output of sizeof variables you'll get 20 because 4 * 5 = 20.
You'd need to divide the sizeof variables by the size of its first element.
As mentioned before, sizeOf returns the size of bytes the array holds.
Unlike java's .length that returns the actual length of the array. Takes a little bit more of knowledge with bytes when it comes to C.
https://www.geeksforgeeks.org/data-types-in-c/
This link tells you a bit more about data types and the memory(bytes) they take up.
You could also do sizeOf yourArrayName/sizeOf (int). sizeOf(datatype) returns the size of bytes the data type takes up.
sizeof will give the size (in bytes) of the variables and will yield different results depending on the data type.
Try:
for (i = 1; i < 5; i++) {
...
}
Related
Let's say we reserved 32 bytes for an array in C, but it turns out we are only using 24 bytes, how can I reduce the reserved memory that is not currently in use? Is this even possible?
I am not using malloc, but I could.
This is the working minimal reproducible example:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
FILE *input;
input = fopen("1.txt", "r");
int arr[4][300];
if (input == NULL) {
printf( "ERROR. Coundn't open the file.\n" ) ;
} else {
for (int i = 0; i < 300; i++) {
fscanf(input, "%d %d %d %d", &arr[0][i], &arr[1][i],
&arr[2][i], &arr[3][i]);
}
fclose(input);
int sze = 0;
for (int i = 0; i < 300; i++) {
for (int j = 0; j < 4; j++) {
if (abs(arr[j][i]) >= 1)
sze += log10(abs(arr[j][i])) + 1;
else
sze++;
if (arr[j][i] < 0)
sze++;
}
}
printf("Size %d kB\n", sze);
}
return 0;
}
Clarification: What I need is to reduce the memory used by each element in the array, if possible. Let's say I have the number 45 stored, it doesn't take up all 4 bytes of an int, so I need to reduce the memory allocated to only 1 byte. As I said, I am not currently using malloc, but I could switch to malloc, if there's a way to what I want to.
If you want to reduce the used space for a value, you need to assign it to an object of different type.
In your example, you start with an int that probably uses 4 bytes on your system. Then you store the value "45" in it, which needs just one byte. Types with size of 1 byte are for example int8_t or signed char.
First, you cannot change the type of a variable, once it is defined. You may store it in another variable.
Second, all elements of an array have to be of the same type.
So the answer for the given example is simply "No."
If you want to "compress" the stored values, you need to roll your own type. You can invent some kind of "vector" that stores each value in as few bytes as necessary. You will need to store the size of each value, too. And you will need to implement access function to each vector element. This is not a simple task.
I'm writing this code in C for some offline games but when I run this code, it says "runtime failure #2" and "stack around the variable has corrupted". I searched the internet and saw some answers but I think there's nothing wrong with this.
#include <stdio.h>
int main(void) {
int a[16];
int player = 32;
for (int i = 0; i < sizeof(a); i++) {
if (player+1 == i) {
a[i] = 254;
}
else {
a[i] = 32;
}
}
printf("%d", a[15]);
return 0;
}
Your loop runs from 0 to sizeof(a), and sizeof(a) is the size in bytes of your array.
Each int is (typically) 4-bytes, and the total size of the array is 64-bytes. So variable i goes from 0 to 63.
But the valid indices of the array are only 0-15, because the array was declared [16].
The standard way to iterate over an array like this is:
#define count_of_array(x) (sizeof(x) / sizeof(*x))
for (int i = 0; i < count_of_array(a); i++) { ... }
The count_of_array macro calculates the number of elements in the array by taking the total size of the array, and dividing by the size of one element.
In your example, it would be (64 / 4) == 16.
sizeof(a) is not the size of a, but rather how many bytes a consumes.
a has 16 ints. The size of int depends on the implementation. A lot of C implementations make int has 4 bytes, but some implementations make int has 2 bytes. So sizeof(a) == 64 or sizeof(a) == 32. Either way, that's not what you want.
You define int a[16];, so the size of a is 16.
So, change your for loop into:
for (int i = 0; i < 16; i++)
You're indexing too far off the size of the array, trying to touch parts of memory that doesn't belong to your program. sizeof(a) returns 64 (depending on C implementation, actually), which is the total amount of bytes your int array is taking up.
There are good reasons for trying not to statically declare the number of iterations in a loop when iterating over an array.
For example, you might realloc memory (if you've declared the array using malloc) in order to grow or shrink the array, thus making it harder to keep track of the size of the array at any given point. Or maybe the size of the array depends on user input. Or something else altogether.
There's no good reason to avoid saying for (int i = 0; i < 16; i++) in this particular case, though. What I would do is declare const int foo = 16; and then use foo instead of any number, both in the array declaration and the for loop, so that if you ever need to change it, you only need to change it in one place. Else, if you really want to use sizeof() (maybe because one of the reasons above) you should divide the return value of sizeof(array) by the return value of sizeof(type of array). For example:
#include <stdio.h>
const int ARRAY_SIZE = 30;
int main(void)
{
int a[ARRAY_SIZE];
for(int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = 100;
// I'd use for(int i = 0; i < ARRAY_SIZE; i++) though
}
I'm unsure how exactly to do this. If anyone has some expert advice that would be extremely helpful!
#define SIZE ((int) (sizeof(digit_count)/sizeof(digit_count[0]))
#define N count
int main()
{
int i, num, count, digit_count[N] = {0};
printf("Enter a number: ");
scanf("%d", &num);
while (num != 0)
{
digit_count[num % 10]++;
num /= 10;
++count;
}
for (i = 0; i < SIZE); i++)
printf("%d occured %d times\n", i, digit_count[i]);
return 0;
}
Use malloc:
int main()
{
int base = 10;
int num, *digit_count;
printf("Enter a number: ");
scanf("%d", &num);
digit_count = malloc (base * sizeof (int));
if (!digit_count)
return -1;
while (num != 0)
{
digit_count[num % base]++;
num /= base;
}
for (i = 0; i < base); i++)
printf("%d occurred %d times\n", i, digit_count[i]);
free(digit_count);
return 0;
}
Since there are always ten digits, there's no reason to use dynamic memory allocation here, but the same pattern used here would work just as well if the number of entries you needed to allocate changed at run time. You could make base change at run time and the program would still work.
Your particular problem
For this particular case, you don't need an array of as many elements as the number has digits, you need an array of 10 elements:
int digit_count[10] = { 0 };
...
// num % 10 is never larger than 9.
digit_count[num % 10]++;
By the way, it would be better to use an unsigned int num and "%u" in the scanf because this will still misbehave for negative numbers, when num % 10 is negative (for C99 and later) or has an unspecified value (older C).
Arrays long enough to hold the digits of a number
In the event that one day you need an array large enough to hold all individual digits of a number, my advice is to use the upper bound; that is to say: enough space to hold the longest number the data type can hold. An approximation that holds beyond megabit integers (i.e., for everything you'll ever encounter) is
#define MAX_DIGITS10(type) (2 + sizeof(type) * CHAR_BIT * 643L / 2136)
...
int digits[MAX_DIGITS10(int)];
This works because 643L / 2136 is a decent approximation of log10(2).
The approach is shamelessly lifted from GNU's libstdc++, which uses
#define __glibcxx_max_digits10(T) \
(2 + (T) * 643L / 2136)
in the C++ standard library header <limits>.
Arrays of variable length
In the event that you one day need an array of truly variable length, you have to calculate the length before allocating the array. Once you have calculated the length, C99 and later, which have VLAs (variable-length arrays), allow you to simply write
size_t calculated_length = calculate_length();
int vla[calculated_length] = { 0 };
// vla goes out of scope like normal arrays; no cleanup necessary
Before C89, you would have to use malloc (or calloc) and free:
size_t calculated_length = calculate_length();
int *heap_array = calloc(calculated_length, sizeof(int));
// or:
int *heap_array = malloc(calculated_length * sizeof(int));
// and when you're done:
free(heap_array);
Note that with malloc it's up to you to check that calculated_length * sizeof(int) does not overflow (most calloc implementations do that internally), and that calloc zero-initializes the memory while malloc does not. This makes calloc a little slower, naturally, but where that is not a problem, my advice is to prefer it over malloc.
VLAs are arguably superior when the array does not need to live beyond the scope in which it is declared, but you should be aware that you cannot use VLAs that are larger than the thread stack, which is usually limited to anything between one and a few megabytes. For large arrays, it is necessary to use the *alloc functions.
This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 8 years ago.
I am trying to use a for loop to assign values to an array in C (I'm using minGW). At first I tried doing:
double flag[5] = {0.1};
but that only assigned the first variable in the array to 0.1. Then I tried doing a for loop to assign each individually. The reason why I don't want to hard code it is because I want the size of the flag variable to be flexible to the user's input. My current code looks like this:
int cnt;
double flag[5];
for (cnt = 0; cnt < sizeof(flag); cnt++) {
printf("sizeof(flag) is %d\n",sizeof(flag));
printf("size is equal to %d and cnt is %d\n",size,cnt);
flag[cnt] = 0.1;
}
printf("size is equal to %d\n",size);
The variable "size" changes from 6 as it was previously determined to a garbage number, and I cannot modify the number of iterations. For example, if I set cnt < sizeof(flag)-1, there is no change. -2,-5, etc no change. However if I drastically reduce the size, it gets stuck in an infinite loop. sizeof(flag) is 40, not 5 like I'd want it to be, but dividing by 8 also gets it into an infinite loop somehow. Any advice?
This question was answered, thank you everyone!
The number of elements of flag array is not:
sizeof (flag)
but
sizeof flag / sizeof *flag
The former is the size in bytes of the array, the latter is the size in bytes of the array divided by the size in bytes of one element of the array.
change :
for (cnt = 0; cnt < sizeof(flag); cnt++)
to
for (cnt = 0; cnt < sizeof(flag)/sizeof(double); cnt++)
use
for (cnt = 0; cnt < sizeof flag / sizeof *flag; cnt++)
{
}
sizeof() returns # of bytes required for that variable which is 5*sizeof(double). So your loop is running for more than 5 times causing overflow.
Apart from the solutions suggested in earlier answers, you can have a macro for size of the array and use this macro and run loop till that value.
#define SIZE 5
.
.
.
int cnt;
double flag[SIZE];
for (cnt = 0; cnt < SIZE; cnt++) {
printf("sizeof(flag) is %d\n",sizeof(flag));
printf("size is equal to %d and cnt is %d\n",size,cnt);
flag[cnt] = 0.1;
}
printf("size is equal to %d\n",size);
I ran the following:
#include <stdio.h>
typedef unsigned short boolean;
#define false 0
#define true (!false)
int main()
{
int STATUS = 0;
int i = 0;
boolean ret = true;
for(i = 0; i < 99999; i++)
{
ret = ret && printf("Hello, World.");
}
if(!ret)
{
STATUS = -1;
}
return STATUS;
}
It completes in just under a second. Typically 0.9 - 0.92.
Then I changed int i = 0; to int *i = 0; and now I am getting execution times under 0.2 seconds. Why the speed change?
Your runtime is dominated by the time required to print to the console. i++ on an int* will increment the pointer by the size of a pointer. That will be either 4 or 8 depending on your computer and compiler settings. Based on the numbers you report, presumably it would be 4. So printf is executed only a quarter as many times.
Typically, printing to a console will be several orders of magnitude larger than any gain with micro optimization you could do to such a loop.
Are you really sure your second version prints hello world 99999 times as well ?
When you're doing for(int *i = 0; i++ ; i < 99999 ) , you're cheking if the pointer value(an address) is less than 99999, which doesn't normally make a lot of sense. Incrementing a pointer means you step it up to point at the next element, and since you have an int*, you'll increment the pointer by sizeof(int) bytes.
You're just iterating 99999/sizeof(int) times.
Your comment on nos's answer confirmed my suspicion: it's pointer arithmetic. When you increment an int pointer using ++, it doesn't just add one to the number, but it actually jumps up by the size of an integer, which is usually 4 (bytes). So i++ is actually adding 4 to the numeric value of i.
Similarly, if you use += on a pointer, like i += 5, it won't just add 5 (or whatever) to the numeric value of i, it'll advance i by the size of that many integers, so 5*4 = 20 bytes in that case.
The reasoning behind this is that if you have a chunk of memory that you're treating as an array,
int array[100]; // for example
you can iterate over the elements in the array by incrementing a pointer.
int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }
and you won't have to rewrite the loop if you use a data type of a different size.
The reason is because the increment operates differently on pointers.
On ints, i++ increments i by 1.
For pointers, i++ increments by the size of the pointed-to object, which will be 4 or 8 depending on your architecture.
So your loop runs for only 1/4 or 1/8 of the iteration count when i is a pointer vs when i is an int.
The correct way to do this test with a pointer would be something like:
int i;
int *i_ptr = &i;
for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
...