Cannot understand why variable i is set to zero? - c

I cannot understand why i is set to 0 right after array is initialized to zero.
The program is working fine because I have reinitialized value of k to i.
But I could not find out why i becomes 0.
And why memset() is clearing the array, or setting the array to 0?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
long long int i = 123456789;
long long int j = 987654321;
long long int cnt = 0;
int array[9] ;
int xyz, k, x, rem, se;
xyz = 0;
// printf("I = %llf", i);
for (i; (i < j) && (cnt < 100000); i++)
{
k = i;
x = 0;
for (se = 0; se <= 9; se++)
{
array[se] = 0;
}
/*************************************************/
i = k; // Here i becomes zero. Why?
/************************************************/
//memset(array, 0, 9);
while(k != 0)
{
rem = k % 10;
for(se = 0; se <= 9; se++)
{
if(rem == array[se])
{
xyz = 1;
break;
}
}
if(rem == array[se])
{
xyz = 1;
break;
}
array[x++] = rem;
k = k / 10;
}
if (xyz != 1)
{
cnt++;
// printf("Cnt = %d ", cnt);
// printf("The value i is = %lld\n", i);
// Sleep(10);
}
xyz = 0;
// printf("The value i is = %lld\n", i);
// printf("Cnt = %d \n", cnt);
fflush(stdin);
}
printf("The value i is = %lld \n", i-1);
return 0;
}

You have a buffer overflow; since the buffer is on the stack, it might be regarded as a form of Stack Overflow†.
int array[9]; // Elements array[0] .. array[8]
...
for (se = 0; se <= 9; se++)
{
array[se] = 0;
}
It must be k that is being overwritten with the extra 0; i is assigned 0 because that's the value in k. You invoke 'undefined behaviour' when you write outside the boundaries of an array, as you did here. Undefined behaviour means that anything can happen and it is OK. Sometimes, it will seem to work; sometimes, there'll be unexpected side effects. Avoid 'undefined behaviour' at all costs.
The idiomatic for loop is:
for (se = 0; se < 9; se++)
array[se] = 0;
Note the < instead of <=.
† There are those who would disagree. See the comments.
You also ask about the (commented out) call to memset():
//memset(array, 0, 9);
The third parameter to memset() is the size in bytes of the area of memory to be set. You are setting 9 bytes out of a total of (probably) 36 in the array, which is unlikely to be what you wanted.
Here, the array is defined in the same function so it is safe and sensible to write:
memset(array, 0, sizeof(array));
If array was a parameter passed to a function, that would not work correctly; you would need a different size. For example:
void somefunc(int array[], int num)
{
...
memset(array, 0, num * sizeof(array[0]));
...
}

You are overwriting the end of the array.
int array[9] ;
for(se = 0; se <= 9; se++)
{
array[se] = 0;
}
In C, arrays are indexed from 0, so the loop goes one step to far. The idiomatic syntax is:
for(se = 0; se < 9; se++)
In other words, use < with the number of elements as the value. Often written to remove the scary numerical constant, like so:
for(se = 0; se < sizeof array / sizeof *array; se++)
This uses the sizeof operator to automatically (at compile-time) compute the proper number of elements, so that if you change the array definition the loop remains correct.

One way to check this is to check the pointer of x and array[9] by printing &x and &array[9].
If they are same, you are surely overwriting as mentioned.

Related

stack corruption by eliminate a printf()

some time ago I tried to program a Mergesort. In some point I got an error that I was able to solve, but still saved the code because have something strange that i don't understand. The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int elem;
void mergesort(elem * arr, unsigned n){
if(n != 1){
if(n == 2){
if(arr[0] > arr[1]){
int change = arr[0];
arr[0] = arr[1];
arr[1] = change;
}
}else{
unsigned i = 0, j = 0, mit = (n+1)>>2, fin = n>>2;
elem * arr_2 = (elem *)malloc(sizeof(elem) * n), * mit_arr = arr+mit;
mergesort(arr, mit);
mergesort(mit_arr, fin);
while(i < mit || j < fin){
if(arr[i] <= mit_arr[j]){
arr_2[j+i] = arr[i];
i++;
}else{
arr_2[j+i] = mit_arr[j];
j++;
}
}
for(i=0; i<n; i++)
arr[i] = arr_2[i];
free(arr_2);
}
}
}
int main(){
unsigned a = 10;
int i;
elem * arr = (elem*)malloc(sizeof(elem) * a);
arr[0] = 12;
arr[1] = 3;
arr[2] = -3;
arr[3] = 22;
arr[4] = 12;
arr[5] = 11;
arr[6] = 4;
arr[7] = 9;
arr[8] = 10;
arr[9] = 2;
printf("something\n"); // 1
mergesort(arr, a);
printf("\n");
for(i=0; i<a; i++){
printf("%d, ", arr[i]);
}
printf("\n");
free(arr);
return 0;
}
The thing is that, despite the fact that the code doesn't do what I want and it seems like there is no error, if I comment out the line marked by 1 (printf("something\\n"); ) then the error "malloc(): corrupted top size" appears. I actually don't know why something like that is possible, so I came here to see if someone have an explanation.
I tried to debug the program with gdb and got the same error, but have more information:
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
but still without idea of what happened.
There are a couple of major issues with your code. These are things you should be able to test yourself by checking whether the values being used by your function are what you expect.
Here's the first issue. You have calculated the length of the first half of the array as (n+1)>>2, and then you assume the length of the remaining array is n>>2. That is simply not true. Shifting a value to the right by 2 binary places is a division by four.
It is far better to use "normal" math instead of attempting to be clever. This reduces the chance for errors, and makes your code easier to read.
unsigned mit = n / 2, fin = n - mit;
The other issue is your merge. You have made your while-loop run until both i and j are out-of-range. But in your loop, it's guaranteed that on at least one of the iterations, one of those values will be out-of-range.
A better way to merge arrays uses three loops. The first one runs until either of the arrays has been merged in, and the remaining two loops will copy the remaining part of the other array.
unsigned x = 0, i = 0, j = 0;
while(i < mit && j < fin){
if(arr[i] <= mit_arr[j]){
arr_2[x++] = arr[i++];
}else{
arr_2[x++] = mit_arr[j++];
}
}
while(i < mit){
arr_2[x++] = arr[i++];
}
while(j < fin){
arr_2[x++] = mit_arr[j++];
}

printing 2 characters and keeping them through dynamically allocated 2d array

Hello I am trying to print something like this with 2d array.
Note that when user enters the same number, character should be printed above existing char.
EXPECTED RESULTS:
Input 1: 3 //user1 inputs 3
****
****
**x*
Input 2: 1 //user2 inputs 1
****
****
y*x*
Input 3: 1 //user1 inputs 1
****
x***
y*x*
current results:
enter first: 3
3***
***
**x
enter second: 1
1******
******
xx****
enter first: 2
2*********
*********
***xxx***
But keeping printed values on its previous places.
The problem is that they don't get printed in right order. And also it seems that I haven't done the best job with 2d array which is dynamically allocated.
Here is something what I've tried:
#include <stdio.h>
#include <stdlib.h>
int num(int term)
{
int number1;
int number2;
if(term==1)
{
scanf("%d", &number1);
return number1;
}
if (term==2)
{
scanf("%d", &number2);
return number2;
}
return 0;
}
void function(int a, int b, int result[], int size)
{
int i = 0;
int j = 0;
int desired_num = 0;
int count = 0;
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
for (i = 0; i < a; i++)
for (j = 0; j < b; j++)
arr[i][j] = ++count;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
{
arr[i][j] = desired_num;
}
if (arr[i][j] == desired_num)
{
printf("%s", "x");
}
else
{
printf("*");
}
}
}
printf("\n");
}
}
int main()
{
int counter = 1;
int i = 0;
int given_number;
int array[20];
for (;;)
{
if (counter % 2 != 0)
{
printf("enter first: ");
given_number = num(1);
printf("%d", given_number);
}
else
{
printf("enter second: ");
given_number = num(2);
printf("%d", given_number);
}
array[i] = given_number;
function(3, 3, array, counter);
counter++;
}
return 0;
}
array[i] = given_number;
i is never changed from the value of 0. You are only ever overwriting the first element of array each iteration. The other 19 elements remain in an indeterminate state.
counter and array are passed to function, as size and result respectively:
This means as size is incremented, it is used as a bounds for accessing elements of result; elements that contain indeterminate values.
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
This will surely lead to Undefined Behaviour as those indeterminate values are used to index arr, effectively accessing random memory offsets. This fact alone makes it hard to reason about the output you are seeing, as really anything is valid.
While perfectly valid, the variable-length array of dynamic allocations is a somewhat perplexing choice, especially considering you fail to free the memory allocated by malloc when you are done with it.
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
int arr[a][b]; would work, given a and b are not stack-crushingly large values (or non-positive). You are, or would be, bounded by the size of array in main anyway.
The triply nested loop is confused at best. There is only logic for printing the x and * characters, so you obviously will never see a y.
For each element of arr, you iterate through each element of result. If the current element of arr equals the value of the column selected by the current value of result ([result[counter] - 1]) in the last row (arr[a - 1]) you print x, otherwise *.
Again UB from utilizing indeterminate values of result, but you can see you are printing a * b * size characters, plus newlines, each iteration.
This is severely flawed.
Some other things of note:
The two branches of the if .. else statement in the num function do the exact same thing, just with different identifiers.
The two branches of the if .. else statement in main are identical, other than the first printf in each, and the integer value passed to num, which have the same effect.
This means the only thing that needs to branch is the printf argument.
A generic function for getting an integer would work fine
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
for use inside main
if (counter % 2 == 0)
printf("enter first: ");
else
printf("enter second: ");
given_number = get_num();
A small issue: printf("%d", given_number); is muddling the output slightly.
There is no reason to repeatedly generate the array. Initialize an array in main to serve as the state of the program. Over time, fill it with the users' selections, and simply print the array each iteration.
Make sure to always check the return value of scanf is the expected number of conversions, and ensure the integers provided by the users will not access invalid memory.
Here is a cursory example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY '*'
#define PLAYER_ONE 'X'
#define PLAYER_TWO 'O'
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
int main(void)
{
const size_t rows = 6;
const size_t cols = 7;
char board[rows][cols + 1];
memset(board, EMPTY, sizeof board);
/* our rows are now strings */
for (size_t i = 0; i < rows; i++) {
board[i][cols] = '\0';
puts(board[i]);
}
unsigned char turn = 1;
while (1) {
printf("Player %s, Enter column #(1-%zu): ",
turn & 1 ? "One" : "Two", rows);
int input = get_num();
if (1 > input || input > cols) {
printf("Invalid column [%d]. Try again...\n", input);
continue;
}
size_t sel = input - 1;
if (board[0][sel] != EMPTY) {
printf("Column [%d] is full! Try again...\n", input);
continue;
}
size_t n = rows;
while (n--) {
if (board[n][sel] == EMPTY) {
board[n][sel] = turn & 1 ? PLAYER_ONE : PLAYER_TWO;
break;
}
}
for (size_t i = 0; i < rows; i++)
puts(board[i]);
turn ^= 1
}
}

array initialisation with 0 in c

I made an int array in C and initialised it with 0 as follows -
int f[10000] = {0};
My program demanded me to reinitialise this array in the end of the loop. So, I performed this step -
f[10000] = 0;
But this didn't worked. I even tried
f[10000] = {0};
but got error in it too. Ultimately, I had to use memset. Can anyone help as in where is the error occurring and why?
EXTRA INFO - I USED ideone.com FOR CODING PURPOSE
For the reference, here is the complete code -
#include <stdio.h>
int main(void) {
int t, n, k, f[10000] = {0}, c[10000] = {0}, i, v, count = 0;
scanf("%d", &t);
while (t--) {
scanf("%d %d", &n, &k);
for (i = 1; i <= n; i++) {
scanf("%d", &v);
if (v == i) {
f[i] = 1;
}
c[v]++;
}
for (i = 1; i <= n; i++) {
if (!f[i] && c[i] >= k) {
count++;
}
}
printf("%d\n", count);
count = 0;
memset(f, 0, 10000);
memset(c, 0, 10000);
//f[10000] = 0; this didn't worked
//c[10000] = 0; this didn't worked
}
return 0;
}
In C, initialization is not the same as assignment, although both use =.
int foo[3] = { 0 };
means "make foo an array of three integers, all initialized to zero", but foo[3] = 0; means "set the fourth element of foo to zero". Clearly different.
And since memset() works in bytes, this:
memset(f, 0, 10000);
is wrong, it should be:
memset(f, 0, sizeof f);
as long as f is a proper array as in your code.
Also beware that very large arrays as automatic variables might not be very portable.
If you did like this
int f[10000] = {0};
then
f[10000] = 0;
is wrong since index starts at 0 in C so you are writing outside the array bounds.
As previously mentioned, you cannot assign to an array. However, you can assign to a struct.
struct foo { int f[1000]; } f = {};
Then,
f = (struct foo){};

Manipulating a global array in a recursive function

I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}
This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);

All Integers have the same value

So I am working on some homework, in which I have to create a global array of 500 random integers between 0 and 99. Then, I have to count how many are greater than 75, and how many are less than 50.
Here is my code:
#include <stdlib.h>
#include <stdio.h>
static int ARRAY[500];
static char str[1];
void main() {
int i = 0;
for (i = 0; i < 500; i++) {
int r = rand() % 99;
ARRAY[i] = r;
}
int gt75 = count75();
int lt50 = count50();
printf("%d\n", str, gt75);
printf("%d\n", str, lt50);
}
int count75() {
int i = 0, counter = 0;
for (i = 0; i < 500; i++) {
int n = ARRAY[i];
if (n > 75) {
counter += 1;
}
}
return counter;
}
int count50() {
int i = 0, counter = 0;
for (i = 0; i < 500; i ++) {
int n = ARRAY[i];
if (n < 50) {
counter += 1;
}
}
return counter;
}
However, after compiling and running my program, I get the following output:
4225008
4225008
This can't be right, as the list should only have 500 elements in the first place. What am I doing wrong?
You have two errors.
First, int r = rand() % 99; should be int r = rand() % 100; Otherwise you just get numbers between 0 and 98.
Second, your printf statements are odd. They should be:
printf("Greater than 75: %d\n", gt75);
printf("Less than 50: %d\n", lt50);
In the current printf statements, the str is cast to an int, which is interpreting the str pointer as an int, thus your strange output.
You're printing a char array with printf using "%d", which is for printing integers. Use "%s" for printing char arrays:
printf("%s\n", str, gt75);
Or, if you're trying to print the value of gt75 as an integer:
printf("%d\n", gt75);
I do not know why you would pass str in this case, though.
When you use "%d", you are telling printf to interpret the input as an int. Since str is actually a char array, it does not output correctly. Instead, you're printing the memory location of str, which is the value of an array.
You are always printing the value of str, which is not an int.

Resources