Null pointer using const instead of variable declaration - c

I have a problem I can't figure out. I wrote this code to shuffle the elements of an array:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const char *array[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
int main(int argc, char **argv)
{
int i, tmp, randomize, size;
size = sizeof(array)/sizeof(*array);
srand(time(NULL));
for(i=size;i>0;i--){
randomize=0+(rand()%size);
tmp=(int)array[i];
array[i]=array[randomize];
array[randomize]=(char*)tmp;
}
for(i=0;i<size;i++)
printf("%s", array[i]);
return 0;
}
When I run the program, this is the iutput:
azlngiwexbv(null)uscphqjyrodmtk
I can't understand why the pointer is sometimes null and I can't understand why, changing the source code in this way:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char **argv)
{
char *array[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
int i, tmp, randomize, size;
size = sizeof(array)/sizeof(*array);
srand(time(NULL));
for(i=size;i>0;i--){
randomize=0+(rand()%size);
tmp=(int)array[i];
array[i]=array[randomize];
array[randomize]=(char*)tmp;
}
for(i=0;i<size;i++)
printf("%s", array[i]);
return 0;
}
Everything works fine.
Thanks.

Start loop from size-1, you are pointing out of array in array[size] (first loop iteration).
for (i=size-1; i>=0; i--)

You should avoid casting whenever possible, and it is rarely necessary to do so.
Unless you plan on using argc and argv[], use the simpler form for main(): int main(void). This will remove some compiler warnings, and you should have these enabled; remove all warnings emitted by your compiler.
You cast a pointer to char to int to store it in tmp, and then you cast tmp back to (char *). Just declare tmp as a pointer to char to start with. The first loop counts down from size to 0; this is out of array bounds to start, but why not just use the conventional loop construction: for (i = 0; i < size; i++)? Also, you should consider using size_t for array indices; it is an unsigned integer type guaranteed to be able to hold any array index, and is also the type returned by the sizeof operator.
Further, in your first version you have declared array as an array of pointers to const chars. You can do this, but you need the temporary storage variable tmp to agree with the const type qualifier.
Here is your code with the above changes. There are no casts, it compiles without warnings, and it works.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
const char *array[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
const char *tmp;
size_t i, size;
int randomize;
size = sizeof(array) / sizeof(*array);
srand(time(NULL));
for(i = 0; i < size; i++){
randomize = (rand() % size);
tmp = array[i];
array[i] = array[randomize];
array[randomize] = tmp;
}
for(i = 0; i < size; i++)
printf("%s", array[i]);
putchar('\n');
return 0;
}

Related

Is there a way to initialize all int array elements to zero except for loop

Is there a way to initialize all int array elements to zero except a for loop where we loop through to set values to zero. Here the size of array is decided by input of user.
#include <stdio.h>
int main() {
int num_cases = 0;
scanf("%d", & num_cases);
int arr_counter[num_cases];
for (int x = 0; x < num_cases; x++) {
arr_counter[x] = 0;
}
}
Yes, you can do that in multiple ways under C standard. For example:
memset() [Stack and Heap]
calloc() [Heap Only]
loops, e.g., do-while, while and for [Stack and Heap]
{ } [Stack Only]
1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int arr[10];
size_t len_arr = sizeof(arr) / sizeof(*arr);
memset(arr, 0, sizeof(arr));
for(size_t i = 0; i < len_arr; i++)
printf("%d\n", arr[i]);
return EXIT_SUCCESS;
}
Note: We can use memset() to set all values as 0 or -1 for integral data types also. It will not work if we use it to set as other values. The reason is simple, memset() works byte by byte.
2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int *arr = calloc(10, sizeof(int));
if(!arr)
{
fprintf(stderr, "bad ptr");
return EXIT_FAILURE;
}
for(size_t i = 0; i < 10; i++)
printf("%d\n", arr[i]);
free(arr);
return EXIT_SUCCESS;
}
Note: You need to keep track of arr maximum length.
Note: malloc() leaves garbage value in your pointer, whereas calloc() uses memset() to initialize them to 0.
Note: You need to free the heap allocated resource.
3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int arr[10];
size_t len_arr = sizeof(arr) / sizeof(*arr);
for(size_t i = 0; i < len_arr; i++)
arr[i] = 0;
for(size_t i = 0; i < len_arr; i++)
printf("%d\n", arr[i]);
return EXIT_SUCCESS;
}
Note: You can use any of your favorite loop.
4
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int arr[10] = {};
size_t len_arr = sizeof(arr) / sizeof(*arr);
for(size_t i = 0; i < len_arr; i++)
printf("%d\n", arr[i]);
return EXIT_SUCCESS;
}
Use calloc function available in stdlib.h
#include<stdio.h>
#include<stdlib.h>
int main(){
int num_cases;
scanf("%d", &num_cases);
int* arr = (int*)calloc(num_cases,sizeof(int));
return 0;
}
To initialize each element of Array you have two approaches:
If you are going for static memory allocation, you can initialize it like this:
int arr[10] = {};
If you are going for dynamic memory allocation, you can use calloc function.
int *arr = (int) calloc(numberOfElementsInArray,sizeOfEachElement);
In your case, it would be like:
int *arr_counter = (int*) calloc(num_cases,sizeof(int));
NOTE: You need to include malloc.h header file to use calloc function.

Int variable subtraction affecting for loop index

I am using a for loop to walk through the elements of char array teste. Within this loop, I am using an int variable called stack_index, for some controls. The program below runs fine, see that, its result is the value of stack_index repeated 18 times (size of char array teste).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t char_size (char* c) {
return strlen(c);
}
int main() {
char teste[] = "Este *teste* string";
size_t n = char_size(teste);
char stack[20];
int stack_index = 0;
for(int i; i < n; i++){
printf("%d", stack_index);
}
}
Result of program above:
0000000000000000000
But, when I add just the line stack_index-- inside the loop, the loop index breaks in some crazy way. See that the result of this program is the values -1, -2 and -3. This result is indicating that the for loop is running only 3 times (instead of 18). But why this is happening? Why subtracting (or adding) 1 from the stack_index variable at each iteration, is affecting the loop index variable i? This makes no sense to me, since the i variable is the index variable of the loop, not stack_index.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t char_size (char* c) {
return strlen(c);
}
int main() {
char teste[] = "Este *teste* string";
size_t n = char_size(teste);
char stack[20];
int stack_index = 0;
for(int i; i < n; i++){
stack_index--;
printf("%d", stack_index);
}
}
Result of program above:
-1-2-3
#Some programmer dude comment answer the problem. I did not initialize the i variable with some initial value (like 0). This mistake was breaking the loop, not the stack_index-- line.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t char_size (char* c) {
return strlen(c);
}
int main() {
char teste[] = "Este *teste* string";
size_t n = char_size(teste);
char stack[20];
int stack_index = 0;
for(int i = 0; i < n; i++){
stack_index--;
printf("%d", stack_index);
}
}
Result of program above:
-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19

Free dynamically allocated memory in C

because I am new in C, I am not sure how to ask it, but here is my Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_SIZE 500
int main(int argc, char *argv[]) {
for (int j=0; j<ARRAY_SIZE; ++j) {
printf("Memory Size: %d\n", j);
int bytes = (1024*1024);
char *data;
data = (char *) malloc(bytes);
for(int i=0;i<bytes;i++){
data[i] = (char) rand();
}
}
//Free all Char*data that I have declared inside the for loop here
return 0;
}
So I need to free my data variables that I have allocated inside the for loop. How is it possible? I am testing some portion of my memory blocks. So I am running it because I wanna see how far it goes. So the above code gets me to that point. Now I am trying to run a loop below threshold point so that I can assure, the memory that I am working with is good and can sustain. To do so, I need to clear the memory that I have created inside the loop.
Thanks in advance
I think you'll want an array of pointers and then free those pointers after the loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_SIZE 500
int main(int argc, char *argv[]) {
char * data[ARRAY_SIZE] = {0};
for (int j=0; j<ARRAY_SIZE; ++j) {
printf("Memory Size: %d\n", j);
int bytes = (1024*1024);
data[j] = (char *) malloc(bytes);
for(int i=0;i<bytes;i++){
data[j][i] = (char) rand();
}
}
for (int j=0; j<ARRAY_SIZE; ++j) {
free(data[j]);
}
return 0;
}
Since you assigned the return value of malloc to data which is defined inside of the loop, that memory is lost at the end of each iteration of the loop.
You need to add a call to free at the bottom of the loop.
for (int j=0; j<ARRAY_SIZE; ++j) {
printf("Memory Size: %d\n", j);
int bytes = (1024*1024);
char *data;
data = (char *) malloc(bytes);
for(int i=0;i<bytes;i++){
data[i] = (char) rand();
}
free(data);
}

strcpy() generates segmentation fault on variable sized array of strings

I'm learning "C" language, I have created a program as below that would copy command-line arguments to another variable sized array (of strings) and print that array starting from index 2.
#include <stdio.h>
#include <string.h>
void print_array(const char* arr[]) {
for (int i = 0; arr[i]; i++) {
printf("%s\n", arr[i]);
}
}
void copy_array(char* dest[], const char* src[]) {
for (int i = 0; src[i]; i++) {
strcpy(dest[i], src[i]);
}
}
int main(int argc, const char* argv[]) {
if (argc < 2)
return 1;
char args[argc][256];
copy_array(args, argv);
print_array(&args[2]);
return 0;
}
The problem is, when I call it via './a.out one two three four five', it throws a segmentation fault. Using gdc, I could see that strcpy() did this. I'm just learning it, can't really find the cause. Can someone point me to what I'm doing wrong?
Your problem is that an array of arrays of char is not the same as an array of pointers to char. That may seem pedantic, but underlying structure is different.
In fact, your compiler should be issuing a warning (if it's not, you should increase your warning levels).
More specifically, if a is an array of array of chars, then a[i] is an address relative to the start of your array that can only be calculated because the compiler knows how large each sub array is (e.g. 256 in your case).
Whereas, if a is an array of pointers to char, no calculation is required, a[i] contains the value of the pointer itself.
By passing an array of arrays where an array of pointers is expected, you are causing the compiler to calculate the address incorrectly (i.e. undefined behavior) and hence your segfault.
If you want to be consistent and use an array of pointers everywhere, your code might look more like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(char* arr[]) {
for (int i = 0; arr[i]; i++) {
printf("%s\n", arr[i]);
}
}
void copy_array(char* dest[], char* src[]) {
int i;
for (i = 0; src[i]; i++) {
dest[i] = malloc(strlen(src[i]) + 1);
strcpy(dest[i], src[i]);
}
dest[i] = NULL;
}
int main(int argc, char* argv[]) {
if (argc < 2)
return 1;
char *args[argc + 1];
copy_array(args, argv);
print_array(&args[2]);
return 0;
}
It seems the copy_array loop execute after the actual length of the array
void copy_array(char* dest[], const char* src[]) {
for (int i = 0; src[i]; i++) {
strcpy(dest[i], src[i]);
}
}
should be changed to
void copy_array(char* dest[], const char* src[], int count) {
for (int i = 0; i < count; i++) {
strcpy(dest[i], src[i]);
}
}
Also print array should be changed to:
void print_array(const char* arr[], int count) {
for (int i = 0; i < count; i++) {
printf("%s\n", arr[i]);
}
}

Why does this for-loop with a pointer not go anywhere?

I'm trying to learn pointers in C, and here is some code I wrote to test it:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int m = 4;
int *n;
n = &m;
printf("%d\n",*n);
for (*n = 0; *n < 100; *n++){
printf("%d\n",*n);
}
}
As expected, that first part printed 4. But the loop did not go further than 4, and did not go to 100 as I tried to make it.
Along with the pointer notation fix suggested by others, I would write this example so that it prints m in the loop, instead of *n, so you can see that manipulating *n does have indeed an effect on the variable to which it points:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int *n, m = 4;
n = &m;
printf("%d\n", *n);
for (*n = 0; *n < 100; (*n)++)
{
printf("%d\n", m);
}
}

Resources