Pointers to the same location - c

I have been struggling with this for quite some time now.
While copying array of strings like in the following code:
#include <stdio.h>
int main (int argc, char* argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf ("%d: %s # %p \n",i,argv[i],argv[i]);
}
char* states[7];
for (i = 0; i <argc; i++)
{
states[i] = argv[i]; // line 36
printf ( "State no.%d: %s # %p \n", i ,states[i],&states[i]);
}
return 0;
}
I obtain the following output:
OUTPUT:
0: ./ex1 # 0x7fff651da366
State no.0: ./ex1 # 0x7fff651d94d0
Shouldn't both the addresses in the output be the same as on line 36 of the code I am making both the pointers point to the same address?

The expression &states[i] gives you the address of where states[i] is in memory, and not where it's pointing. Drop the address-of operator to fix the problem.

Related

char** argv passed as array of string

What I know about this code is that in the void cylinder function char** argv is a array of string and numbers are stored in this. I dont know how to convert this array into the int values and then use it.
void cylinder(int argv_size, char** argv){
//comlete this code
}
int main(){
int n;
scanf("%i",&n);
char* *a = malloc(sizeof(char*) * n);
for(int i = 0; i<n;i++){
a[i] = (char *)malloc(1020 * sizeof(char));
scanf("%s",a[i]);
}
cylinder(n,a);
return 0;
}
You might want to check if some arguments/ no arguements have been passed:
if(argc==1)
printf("\nNo Command Line Argument Passed Other Than Program Name");
if(argc>=2)
{
printf("\nNumber Of Arguments Passed: %d",argc);
for(int counter=0 ; counter<argc ; counter++)
printf("\nargv[%d]: %s",counter,argv[counter]);
}
Then, to convert the passed integer(passed as a string) value use atoi, like: atoi(argv[1]) if only one integer value has been passed.
Note: use #include<stdlib.h> for atoi()
I see some disadvantage in your code:
scanf("%s",a[i]);
Should change to (see disadvantages of scanf ):
scanf("%1019s",a[i]);
//OR
fgets(a[i], 1020, stdin);
You should check the result of malloc function, and do not cast malloc as i see you allocated for a[i]:
char* *a = malloc(sizeof(char*) * n);
if(!a) {
//handle the error
return -1; // for example
}
and
a[i] = malloc(1020 * sizeof(char));
if(!a[i]) {
//handle the error
}
You have to free the memory of each a[i] and a after cylinder function to avoid memory-leaks.
For cylinder function:
void cylinder(int argv_size, char** argv){
for(int i = 0; i < argv_size; i++) {
// convert argv[i] to int by using sscanf, atoi, strol, etc.
// for example i use atoi function:
printf("value of (int)argv[i] = %d", atoi(argv[i]);
}
}
You can also find other function for converting string to int in this link How to convert a string to integer in C?

Declaring and copying an array of char strings in c

I made a c program that attempts to add the values of one string array to another using a separate method:
#include <stdio.h>
#include <stdlib.h>
void charConv(char *example[])
{
example= (char* )malloc(sizeof(char[4])*6);
char *y[] = {"cat", "dog", "ate", "RIP", "CSS", "sun"};
printf("flag\n");
int i;
i=0;
for(i=0; i<6; i++){
strcpy(example[i], y[i]);
}
}
int main() {
char *x[6];
charConv( *x[6]);
printf("%s\n", x[0]);
}
However it keeps returning a segmentation fault. I'm only beginning to learn how to use malloc and c in general and its been puzzeling me to find a solution.
To pin-point your problem: you send *x[6] (here - charConv( *x[6]);) which is the first char of the 7'th (!!!) string (Remember, C is Zero-Base-Indexed) inside an array of 6 string you didn't malloc -> using memory you don't own -> UB.
Another thing I should note is char[] vs char * []. Using the former, you can strcpy into it strings. It would look like this:
'c' | 'a' | 't' | '\0' | 'd' | 'o' | 'g' | ... [each cell here is a `char`]
The latter ( what you used ) is not a contiguous block of chars but a array of char *, hence what you should have done is to allocate memory for each pointer inside your array and copy into it. That would look like:
0x100 | 0x200 | 0x300... [each cell is address you should malloc and then you would copy string into]
But, you also have several problems in your code. Below is a fixed version with explanations:
#include <stdio.h>
#include <stdlib.h>
void charConv(char *example[])
{
// example= (char* )malloc(sizeof(char[4])*6); // remove this! you don't want to reallocate example! When entering this function, example points to address A but after this, it will point to address B (could be NULL), thus, accessing it from main (the function caller) would be UB ( bad )
for (int i = 0; i < 6; i++)
{
example[i] = malloc(4); // instead, malloc each string inside the array of string. This can be done from main, or from here, whatever you prefer
}
char *y[] = {"cat", "dog", "ate", "RIP", "CSS", "sun"};
printf("flag\n");
/* remove this - move it inside the for loop
int i;
i=0;
*/
for(int i=0; i<6; i++){
printf("%s\t", y[i]); // simple debug check - remove it
strcpy(example[i], y[i]);
printf("%s\n", example[i]); // simple debug check - remove it
}
}
int main() {
char *x[6];
charConv( x); // pass x, not *x[6] !!
for (int i = 0; i < 6; i++)
{
printf("%s\n", x[i]); // simple debug check - remove it
}
}
As #MichaelWalz mentioned, using hard-coded values is not a good practice. I left them here since it's a small snippet and I think they are obvious. Still, try to avoid them
You need to start by understanding the pointers and some other topics as well like how to pass an array of strings to a function in C etc.
In your program, you are passing *x[6] in charConv() which is a character.
Made corrections in your program -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void charConv(char *example[], int num)
{
int i;
for (i = 0; i < num; i++){
example[i] = (char* )malloc(sizeof(char)*4);
}
const char *y[] = {"cat", "dog", "ate", "RIP", "CSS", "sun"};
for(i = 0; i < num; i++){
strcpy(example[i], y[i]);
}
}
int main() {
char *x[6];
int i = 0;
charConv(x, 6);
/* Print the values of string array x*/
for(i = 0; i < 6; i++){
printf("%s\n", x[i]);
}
return 0;
}

Function to count the sum of an array

Right, this is (the last) assignment for my C introduction web class.
The assignment presents the main program, does not explain anything about it and tells you to write a function to print and sum the array in it.
However I don't really understand what is going on in the main program.
Translated for your convenience;
Source code:
#include <stdio.h>
#include <stlib.h>
void print_count(int *, int);
int main(int argc, char *argv[]) {
int x, sum = 0, size = 0, array[5];
if (argc == 6) {
/* Program name and parameters received from command line */
for (x = 0; x < argc - 1; x++) {
array[x] = atoi(argv[x + 1]);
}
print_count(array, size);
} else {
printf("Error\n");
}
return 0;
}
Now I am completely clueless as to how to start writing the program requested and what variables to call/how to write the function.
Edit3: completed exercise
void print_count(int *array, int size) {
int i;
int sum = 0;
printf("Elements: ");
for (i = 0; i <= size; i++) {
printf("%d ", (array[i]);
sum = sum += array[i]);
}
printf("\nSum = %d ", sum);
return 0;
}
I would like to understand what is going on in the main program and preferably come to an answer on how to actually write the function by myself.
This:
array[5] = atoi(argv[x+1]);
is clearly wrong, it always tries to assign to array[5] which is out of bounds. It should be:
array[x] = atoi(argv[x + 1]);
This converts the x + 1:th argument from string format into an integer, and stores that in array[x]. If you're not familiar with the standard function atoi(), just read the manual page.
So if you start the program like this:
./myprogram 1 2 3 4 5
That has 6 arguments (the first is the name itself), and will end up with array containing the numbers one through five.
Then in the summing function, the first line should be something like:
void print_count(int *array, int size)
so that you give names to the arguments, which makes them usable in the function. Not providing names is an error, I think.
And it doesn't need to "interact" with main() more than it already does; main() calls print_count(), passing it a pointer to the first element of array and the length of the array, that's all that's needed to compute the sum.
Your print_count function has a few issues:
The loop runs one step too far: i should vary between 0 and size-1 included. The standard idiom for this loop is:
for (i = 0; i < size; i++) {
...
Incrementing sum is simply done with:
sum += array[i];
There is an extra ( on the first printf line.
You should print a newline after the output.
Returning 0 from a void function is invalid.
Here is a corrected version:
void print_count(int *array, int size) {
int i;
int sum = 0;
printf("Elements: ");
for (i = 0; i < size; i++) {
printf("%d ", array[i]);
sum += array[i]);
}
printf("\nSum = %d\n", sum);
}
the following proposed code:
cleanly compiles.
explains what is being accomplished at each step of the 'main()' function.
properly outputs error messages to 'stderr'.
implements the typical method to announce an error in the number of command line parameters.
Now the proposed code with explanatory comments:
#include <stdio.h> // printf(), fprintf()
#include <stdlib.h> // atoi(), exit(), EXIT_FAILURE
void print_count(int *, int);
int main(int argc, char *argv[])
{
if (argc != 6)
{
fprintf( stderr, "USAGE: %s int1 int2 int3 int4 int5\n", argv[0] );
exit( EXIT_FAILURE );
}
// implied else, correct number of arguments
// only declare variables when they are needed
int array[5];
// place each command line parameter into 'array',
// except program name
// I.E. skip the program name in argv[0]
for( int i = 1; i < argc; i++ )
{
// array[] index starts at 0, but loop counter starts at 1
array[i-1] = atoi(argv[i]);
} // end for( each value pointed at by argv[], except program name )
// print sum of command line parameters to stdout
int size = argc-1; // number of command line parameters after program name
print_count(array, size);
return 0;
} // end function: main

Memory map while developing C application with Eclipse

Just for educational purpose I have written C code that gets out of array bound:
int main( int argc, char ** argv ) {
char *cp = "dabsf";
cp=cp+10;
printf("%c",*cp);
return 0;
}
I have letter n in output.
Is it possible somehow to see whole memory map and see what bytes are near cp array and find where is n?
I'm using MinGW compiler.
Here's some code to print memory out, you can use it to print memory around after any pointer you want (trying to print too much might give you an access violation, especially trying addresses before your first variable):
#include <stdio.h>
void printMemory(void *address, int rows, int cols) {
for(int r = 0, c; r < rows; ++r) {
c = 0;
printf("%8p ", (void *)(((unsigned int*)address) + (r*cols + c)));
for(; c < cols; ++c) {
printf("0x%08x ", *(((unsigned int *)address) + (r*cols + c)));
}
printf("\n");
}
}
int main(void) {
char *test = "Hello World!";
unsigned int value1 = 0xABABABAB;
unsigned int value2 = 0xDEADBEEF;
unsigned int value3 = 0xCAFEBABE;
printf("%s, %d, %d, %d\n", test, value1, value2, value3);
printMemory(test, 4, 2);
printf("\n");
printMemory(&value1, 1, 3);
return 0;
}
The output is (in my case the string was stored in a different place than the integers):
Hello World!, -1414812757, -559038737, -889275714
0x80486ad 0x6c6c6548 0x6f57206f
0x80486b5 0x21646c72 0x2c732500
0x80486bd 0x2c642520 0x2c642520
0x80486c5 0x0a642520 0x01000000
0xbf8aab50 0xabababab 0xcafebabe 0xdeadbeef
Also this works for debugging, but do not do this in real code, accessing memory addresses that aren't for your variables is undefined behavior.
To print the memory map of 10 positions from cp:
#include <stdio.h>
int main(void) {
int i;
char *cp = "dabsf";
printf("Address of 1st element of cp %p\n", cp);
for(i=1;i<=10;i++)
{
printf("Address of %c is %p\n",*(cp+i), cp+i); // cp+i is the same as &(*(cp+i))
}
return 0;
}
To get the address of any element after the array:
cp = cp + 8;
printf("Element at cp+8 is %c\n", *cp);
printf("Address of cp+8 is %p\n", cp);
Note: the output of the code just above may change in successive runs of the code.

Converting 'integer strings' to integer array

I'm trying to pass in an array of integers into my program. Is there a better way to convert it to integers? I'm currently getting an error: "Variable sized object may not be initialized"
for(i = 0; i < argc; i++)
{
int arr[i] = atoi(argv[i]);
}
Assuming argc and argv are the arguments passed to main, it is unlikely that argv[0] is something that you want to convert into an integer. argv[0] usually contains the name of the program.
Your code snippet is declaring an array local to the loop body. What you likely want is an array defined outside the loop body, and you want to assign to individual array elements within the loop body.
int arr[argc];
for(i = 1; i < argc; i++)
{
arr[i] = atoi(argv[i]);
}
You are declaring your array arr every time you loop.
change your loop like this:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int arr[argc];
int i=0;
for(i = 0; i < argc-1; i++)
{
arr[i] = atoi(argv[i+1]);
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
Here is the output:
Sukhvir#Sukhvir-PC ~
$ gcc -Werror -Wall -g -o test test.c
Sukhvir#Sukhvir-PC ~
$ ./test 3 4 5
arr[0] = 3
arr[1] = 4
arr[2] = 5

Resources