Define integer (int); What's the default value? - c

int i;
int data[5] = {0};
data[0] = i;
What's the value in data[0]?
Also, what's the meaning of this line?
if (!data[0]) { ... }

In most cases, there is no "default" value for an int object.
If you declare int i; as a (non-static) local variable inside of a function, it has an indeterminate value. It is uninitialized and you can't use it until you write a valid value to it.
It's a good habit to get into to explicitly initialize any object when you declare it.

It depends on where the code is written. Consider:
int i;
int data[5] = {0};
void func1(void)
{
data[0] = i;
}
void func2(void)
{
int i;
int data[5] = {0};
data[0] = i;
...
}
The value assigned to data[0] in func1() is completely deterministic; it must be zero (assuming no other assignments have interfered with the values of the global variables i and data).
By contrast, the value set in func2() is completely indeterminate; you cannot reliably state what value will be assigned to data[0] because no value has been reliably assigned to i in the function. It will likely be a value that was on the stack from some previous function call, but that depends on both the compiler and the program and is not even 'implementation defined'; it is pure undefined behaviour.
You also ask "What is the meaning of this?"
if (!data[0]) { ... }
The '!' operator does a logical inversion of the value it is applied to: it maps zero to one, and maps any non-zero value to zero. The overall condition evaluates to true if the expression evaluates to a non-zero value. So, if data[0] is 0, !data[0] maps to 1 and the code in the block is executed; if data[0] is not 0, !data[0] maps to 0 and the code in the block is not executed.
It is a commonly used idiom because it is more succinct than the alternative:
if (data[0] == 0) { ... }

if an integer is declared globally then it is initialized automatically with zero
but if it is local then contains garbage value until and unless itis given some value

If an integer is not initialized, its value is undefined as per C

Since you've included the ={0};, the entire array is filled with zeros. If this is defined outside any function, it would be initialized with zeros even without the initializer. if (!data[x]) is equivalent to if (data[x] == 0).

// File 'a.c'
#include <stdio.h>
void main()
{
int i, j , k;
printf("i = %i j = %i k = %i\n", i, j, k);
}
// test results
> $ gcc a.c
> $ ./a.out
> i = 32767 j = 0 k = 0

Related

Simple if statement in C always return true

I dont have time to explain it deeply, its very simple code but the function always return 'y'(=true)
It is expected to write each number from 1 to squareroot of the generated random number and decide whether it is dividable or not but when i run it, somehow the if statement in the function always return true
#include <stdio.h>
#include <stdlib.h>
int a,b,i;
char c;
char abcd(char c);
int main()
{
srand(time(NULL));
int a=rand()%512;
b=sqrt(a);
i=1;
do{
if(abcd(c)=='y')printf("number %d is dividable by %d\n",a,i);
else printf("number %d is not dividable by %d\n",a,i);
i++;
}while(i<=b);
return 0;
}
char abcd(char c)
{
if(a%i==0)return'y';
else return 'n';
}
When you declare int a inside main as
int a=rand()%512;
you are shadowing your global variable a. The a in main is a different variable that has scope only local to the function main. Therefore, when you are using the value a inside char abcd(char c), this value is the global variable a which is default initialized to 0.
Also, why are you passing a char c variable to function abcd. You aren't using it. Please consider renaming your functions to something that more clearly describes their intent.
You have two different variables a:
one declared at file scope
int a,b,i;
and one declared in main():
int a=rand()%512;
Within its scope (almost all of main()), the latter shadows the former. Elsewhere, such as in function abcd(), only the former is visible. The former is default initialized to 0 and no other value is ever assigned to it, so no matter what value i takes, inside abcd(), the expression a%i evaluates to 0.
This is a good lesson in avoiding file-scope variables. Functions should operate on data accessed directly or indirectly through their parameters, or obtained from an external source. It is poor form for functions to exchange data through file-scope variables. Moreover, it was a red flag to me that your function abcd() declares a parameter that it never uses. Suggested variation:
char abcd(int dividend, int divisor) {
return (dividend % divisor) ? 'n' : 'y';
}
Or even better (because better name and more appropriate return type):
_Bool is_divisible(int dividend, int divisor) {
return !(dividend % divisor);
}
The reason yours doesn't work is because the variable a was declared in a separate scope from the abcd function. The a variable you use inside the abcd function is automatically set to 0, which is why it returns true every time (0 % anything is 0).
When you call abcd, you would need to pass a inside the parameters for it to use the correct value.
But really you don't need the abcd function, you can save a lot of code and directly check if it's divisible. This code should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int a, b, i;
char c;
int main()
{
srand(time(NULL));
int a = rand() % 512;
b = sqrt(a);
i = 1;
do {
if (a%i == 0)printf("number %d is dividable by %d\n", a, i);
else printf("number %d is not dividable by %d\n", a, i);
i++;
} while (i <= b);
return 0;
}

If loop without a boolen condition in c

what actually happens in if statement here?
#include <stdio.h>
int x;
void main()
{
if (x)
printf("hi");
else
printf("how are u");
}
printf("hi"); is ran if x is non-zero, and printf("how are u"); runs if x is zero.
The conditional check formally uses an int type in C (with any other type implicitly converted to an int prior to the evaluation); not a Boolean type.
Note that x is initialised automatically to 0 in your case as it's at global scope.
Here
if (x)
takes the first branch if x is not 0, otherwise the second (else) branch.
In C any non zero value is equivalent to the truth and zero to false
So any value is considered as valid logical (even pointers).
int *p = malloc(40);;
if (p) printf("Good!!");
in your example x will be equal zero (unitialized global variables are zeroed) and the else printf will be executed.
As the any value which can be converted to integer is valid as logical we can write very short functions like this:
char *strcpy(char *dest, const char *src)
{
char *saveddest = dest;
while(*dest++ = *src++);
return saveddest;
}
Here int x; is a global uninitialized variable. Compiler initialized the global int variable with 0. In C, 0 means false and 1 means true. Thats why it will print the else part because if(0) means false and compiler will execute the else block i.e. how are u.
Please visit the link for better understanding:
https://www.geeksforgeeks.org/g-fact-53/

First Element of array not empty, pointer dereference

i am writing code for a microcontroller.
I have the following example so far:
// weekly table[timeslot][day]
const int _rows = 7;
const int _cols = 12;
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
// pointer pointing start of array weekly array
uint32_t *ptr_weekly_table = &weekly_table[0][0];
int progress_weekly_table = 0;
bool weekly_table_full = false;
/*
* according to progress_weekly_table save a value in the weekly_table
*/
void append_weekly_table( uint32_t value)
{
//insert element
printf(*ptr_weekly_table);
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set flag
if (progress_weekly_table > _num_weekly_table) {
weekly_table_full = true;
}
}
During the main loop I run this line:
append_weekly_table(1);
But the resulting array does not have a 1 as the first element, instead a 3200171746 (reproducable).All other elements in the array are 1 if i continue to run append_weekly_array.
What is my error here? Quite new to pointers so I don't know if this is the issue.
For starters these declarations
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
are invalid if they are declarations in the global namespace because 1) you may not initialize a variable with the static storage duration with a non-constant expression and 2) you may not declare Variable Length Arrays with the static storage duration.
It seems you are compiling your program as a C++ program instead of as a C program.
In any case the function append_weekly_table is invalid.
For example this statement
printf(*ptr_weekly_table);
does not make sense because the first parameter of the function has type const char *.
int printf(const char * restrict format, ...);
^^^^^^^^^^^^
And initially the object *ptr_weekly_table has inderterminate value (if the program is a C program and the array does not have the static storage duration; otherwise the object is zero initialized).
Also this condition
if (progress_weekly_table > _num_weekly_table) {
weekly_table_full = true;
}
also is wrong. It should be written like
if (progress_weekly_table == _num_weekly_table) {
weekly_table_full = true;
}
If you want to compile your program as a C program then the variables _rows and _cols must be declared at least like
enum { _rows = 7, _cols = 12 };
Also it is a bad idea to use leading underscores in variable names because such names are reserved by the system.
Here is a demonstrative C program that can compile.
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
enum { _rows = 7, _cols = 12 };
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
// pointer pointing start of array weekly array
uint32_t *ptr_weekly_table = &weekly_table[0][0];
int progress_weekly_table = 0;
bool weekly_table_full = false;
void append_weekly_table( uint32_t value)
{
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set flag
if (progress_weekly_table == _num_weekly_table) {
weekly_table_full = true;
}
}
int main(void)
{
append_weekly_table( 1 );
printf( "ptr_weekly_table[0] = %d\n", *ptr_weekly_table );
return 0;
}
The program output is
ptr_weekly_table[0] = 1
You could substitute these two statements
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set
with one statement
ptr_weekly_table[progress_weekly_table++] = value;
The main problem is most likely this this:
printf(*ptr_weekly_table);
The expression *ptr_weekly_table an uint32_t value. Not a string (char *) which printf expects. Because you in effect pass a null pointer (since ptr_weekly_table[0] is supposedly zero) then you will ask printf to print whatever "string" is at location zero, and that will lead to undefined behavior.
To print the correct value use something like
printf("%"PRIu32"\n", ptr_weekly_table[0]);
See e.g. this format specifier macro reference for information about PRIu32.
And as you can see I used ptr_weekly_table[0] to get the first value of the array. The expressions ptr_weekly_table[0] and *ptr_weekly_table are equal.
In fact, for any pointer or array p and index i, the expression p[i] is exactly equal to *(p + i). Which means *(ptr_weekly_table + progress_weekly_table) could be written ptr_weekly_table[progress_weekly_table] (which is a couple of characters less to write, as well as often more readable).

Why does this initialize the first element only?

I'm trying to figure out why initializing an array with int buckets[AS] = { 0 }; is not setting all the elements to zero. Perhaps it is a compiler optimization, in which case would volatile be acceptable? volatile int buckets[AS] = { 0 };.
Second question, why is only the first element initialized to 1 here? Doesn't this fall under:
C99 [$6.7.8/21]
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
Problem code:
#include <stdio.h>
#define AS 100
int buckets[AS] = { 1 };
int main()
{
int i;
for(i = 0; i < AS; i++) {
printf("%d", buckets[i]);
}
return 0;
}
EDIT:
Changing optimization level from -o0 to default eliminates the issue. Working with STM32 Kiel IDE micro-controllers.
EDIT EDIT:
This is the code causing trouble. Compiler optimizing away for loop?
// Initialize this to 1 as when initializing to 0 and clearing some elements are non-zero
// Possibly a compiler bug? Changing optimization level from -o0 to default eliminates the issue
uint16_t pulse_time_hist[NUM_BUCKETS] = {1};
// Resets all values stored in the histogram
void clearHist() {
unsigned int i;
for (i = 0; i < NUM_BUCKETS; i++) {
pulse_time_hist[i] = 0;
}
}
EDIT EDIT EDIT:
I'm not a compiler guy at all btw. Here is my compiler control string
-c -cpu Cortex-M4.fp -D__EVAL -g -O0 -apcs=interwork -split_sections ...
Running without -c99 currently.
In the quotation "... shall be initialized implicitly ..." a value for initialization is not mentioned, so rest of array is initialized by default value, and for number types this default value is 0.
To continue the topic try the following snippet
#include <stdio.h>
#define N 10
int arr1[N];
int main()
{
int arr2[N];
int i;
for (i = 0; i < N; i++) {
printf("%d ", arr1[i]);
}
printf("\n");
for (i = 0; i < N; i++) {
printf("%d ", arr2[i]);
}
return 0;
}
and try to understand why the output is
i.e. why global/static objects (like arr1) are initialized without initializers, but local/automatic/stack-allocated (like arr2) are not.
UPDATE:
Section 6.7.8 Initialization of C99 standard said:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.
This is because the missing values are automatically initialized to zero. If you want to initialize every element to 1, you need to have this :
int buckets[AS] = {1, 1, 1, ..., 1}; //100 times
which clearly isn't feasible.
You may also want to read this answer as well.
int buckets[AS] = { 1 };
In which case you can omit some part of the initializer and the corresponding elements will be initialized to 0.
int buckets[AS] = { 1 }; //initialize to 1,0,0,0,0...
If you are trying to initialize all elements of the array to 1 there is a GCC extension you can use with the following syntax:
int buckets[AS] = {[0 … 99] = 1 };

C: When is a variable or value considered used?

I am cleaning up some code from a Coverity issue and have a situation where a pointer local to a function is used earlier on is a function for comparison, then later on it is assigned to point else where but it is never de-referenced or used to assign something to its value. Coverity is saying that it is an unused pointer value - so I am thinking to cast it to a void to indicate the pointer is not used after that point. I am wondering when is a value or variable considered used in a program? Here is a code sample explaining my situation:
In the sample below Coverity would flag the fltr_ptr as not being used after its two assignments at the end of the sample
int initialise (void)
{
// pointer first decalred and defined
FILTER_PTR fltr_ptr = NULL;
// pointer given valid value
fltr_ptr = global_val->filter_group[index];
// second use of fltr_ptr
if ( TRUE == fltr_ptr -> being_used)
{
// first use of fltr_ptr
if ( TRUE != close_filter ( fltr_ptr -> Filter)
{
// print error
}
// do more code
// fltr_ptr assigned first time , value not used should it be (void)fltr_ptr?
fltr_ptr = Free_Memory (fltr_ptr, sizeof(FILTER_PTR));
}
else
{
return 1;
}
for ( number of iterations )
{
// fltr_ptr assigned again but value not used should it be (void)fltr_ptr?
fltr_ptr = global_val->filter_group[index];
}
return 0;
}
Coverity points to you that you assign to fltr_ptr in the last for loop but you do nothing with this value. Why assign at all? Casting to void could possibly fix the warning, but the first thing to fix should be either to use the pointer somehow, or stop assigning to it.
To answer the title question, a variable is considered unused when "it is initialised or assigned to and then disposed of without being read."
int main()
{
int i;
int j = 1; // both i and j are unused at this point
int i = j * 2; // j is now 'used', the new value of i is unused
printf("%d",j);//j is used again
} // i goes out of scope without being used.
note that the definition isn't also "if it is assigned to without being read" as this would indicate that there was a problem with the following:
unsigned int find_max_index(int a[], int size)
{
unsigned int i;
unsigned int maxval = 0;
unsigned int maxindex = 0;
for (i = 0; i< size; i++){
if (a[i]>maxval){
maxval = a[i];
maxindex = i;
}
}
return maxindex;
}
As in this code maxindex can be assigned to multiple times without being read.
Looking back at my original example, we can eliminate i without any change to the program. This reduces the complexity of the program, removes redundant operations (though the compiler should do this when optimising too) and reduces the chance of programmer error in the future:
//FUNCTIONALLY THE SAME AND SIMPLER
int main()
{
int j = 1; // j is unused at this point
printf("%d",j);// j is used
}
In the same way, you can remove this entire loop:
for ( number of iterations )
{
// fltr_ptr assigned again but value not used should it be (void)fltr_ptr?
fltr_ptr = global_val->filter_group[index];
}
(You remove the assignment and get an empty loop. as this is a long nop, it can also be removed)

Resources