How to access char array using an int pointer? - c

Hi how to access character array using integer point.
char arr[10] = {'1','2','3','4','5','6','7','8','9','10'};
int *ptr;
How i can print values of 'arr' using pointer ptr?

It is a little unclear what your goal is, but trying to print out a character array with an integer pointer is a bit like trying to get to the second step taking four-steps at a time. When you tell the compiler that you would like to reference a memory address with an integer pointer, the compiler knows that an integer is sizeof (int) bytes (generally 4-bytes on x86/x86_64). So attempting to access each element in a character array with an integer pointer and normal pointer arithmetic wouldn't work. (you would be advancing 4-bytes at a time).
However printing the character array though an integer pointer is possible if you use the integer pointer for the starting address of the array and advance the pointer by the number of characters in the array by casting back to char. While it is doubtful this is your goal, the plain statement of your question seems to suggest it. To accomplish this, you could:
#include <stdio.h>
int main (void)
{
char arr[] = {'1','2','3','4','5','6','7','8','9'};
int *ptr = (int *)arr;
unsigned int i;
for (i = 0; i < sizeof arr; i++)
printf (" %c", (*(char *)ptr + i));
putchar ('\n');
return 0;
}
Output
$ ./bin/char_array_int_ptr
1 2 3 4 5 6 7 8 9
Note: your original initialization of your array with a character '10' was invalid. If this was an assignment, it is likely intended to expose you to how pointer arithmetic is influenced by type and the ability to cast from and to type char (without violating strict aliasing rules)

If you are just after the integer values you can print out the characters as integers
for (i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i)
{
printf( "%d ", arr[i] );
}

Using a pointer of the wrong data type to access anything is undefined behavior, thus making it not something you want to do. If you want to cast a char to an integer, you can do that. If you want to print the integer value of a char, you can do that too.
But using a pointer type integer to access a char array is undefined behavior.

Related

Assigning a string to a char pointer is valid but assigning an integer to int pointer is invalid in C. Why?

A char pointer can be assigned an arbitrary string but an integer pointer cannot be assigned an integer. Since both of them are pointers and contains address. Why is assigning string valid but an integer invalid in C to a pointer before dynamic allocation.
#include<stdio.h>
int main()
{
char *s = "sample_string"; // valid
printf("%s\n", s);
int *p = (int)5; // invalid
printf("%d\n", *p);
return 0;
}
Which gives output :
sample_string
Segmentation fault (core dumped)
What is the reason behind it? Although both of them are invalid in C++.
There is no "string type" in C. A "string", by C definition, is an array of char with a zero byte at the end.
The type of "sample_string" is char[14], which can be assigned to a pointer.
The type of (int)5 is int, which cannot[1].
The segmentation fault happens because you are accessing the address 0x00000005, which is not valid.
[1]: Technically you can. But if you want to dereference that pointer successfully, you have to take care that the address value of that integer has the proper alignment for the type, and is referring to a valid object of the type. Which is why compilers generate a warning if you don't explicitly cast that integer to pointer type in the assignment, to indicate that you do know what you're doing.
char *s = "sample_string"; Here "sample_string" is a string literal which is a const char[] in C++. It's implicitly converted to const char*. You'll get a warning though since you're assigning it to a char*.
int *p = (int)5; Here 5 is just an integer. Since you're assigning this a pointer, that means it's an invalid pointer value. And hence when it's referenced, you get a segfault.
This is simple:
A char object may hold a char value: char x = 'a';.
An int object may hold an int value: int x = 3;.
A char * object may point to an array of char: char *p = "abc";.
An int * object may point to an array of int: int *p = (int []) {1, 2, 3};.
(In this answer, “point to an array” is short for “point to the first element of an array”.)
In C, a string literal, such as "abc", is effectively an array of char, including a null character at the end. Also, the text above, (int []) {1, 2, 3}, is a compound literal that creates an array of int. So both "abc" and (int []) {1, 2, 3} are arrays. When an array is assigned to a pointer, the C implementation automatically converts it to a pointer to its first element. (This conversion occurs whenever an array is used in any expression other than as the operand of sizeof, as the operand of unary &, or, if it is a string literal, as the initializer for an array.)
The convention is that strings are arrays of char (char[]) and a pointer to a string points to the first element of this char array, similar like a pointer to an array always points to its first element by default, i.e for an int array
int a[10];
int *p;
p=&a
points to the first element of a that is a[0] in index notation
but an integer pointer cannot be assigned an integer.
Not quite. In C an integer can be assigned to a pointer - with certain conditions. Yet this only sets the pointer to 5, not that p points to an int with the value of 5. *p attempts to read what is at address 5 and interpret that location as an int. Certainly access to address 5 is invalid and causes a seg fault.
Even if those conditions are met (see below), this is certainly not what OP is seeking which I assume to be set the pointer p to point to someplace with the value/type of 5/int in it.
(int) {5} is a compound literal, available since C99. Here it is an int with the value of 5 and code takes the address of that object and assigns that address to p.
// int *p = (int)5;
int *p = & ((int) {5});
printf("%d\n", *p); // prints 5
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. C17dr § 6.3.2.3 5

Difference between int*a and char *a?

What is the difference between char *a and int *a as both work on Code Blocks for storing character pointer eg.
char *c, k = '$';
int *j;
j = &k;
printf("%c\n%p\n%c\n", k, j, *j);
c = &k;
printf("%c\n%p\n%c", k, c, *c);
Activate diagnostics and don't ignore them (-Wall -Wextra -pedantic-errors).
The compiler should tell you that you are doing something disallowed.
See here on coliru: http://coliru.stacked-crooked.com/a/31acb5b670254167
main.cpp:7:7: error: incompatible pointer types assigning to 'int *' from 'char *' [-Werror,-Wincompatible-pointer-types]
j = &k;
^ ~~
Answering your question, a char is an integer-type of lower rank than int (meaning potentially (and in practice nearly guaranteed) smaller size and value-range), and thus pointers to either are different types too.
Using a pointer of wrong type to access an object (with few exceptions) is UB.
Interpreting a character object as an integer
printf("%c\n%p\n%c\n", k, j, *j);
or storing the address of a char into an int pointer
j = &k;
is undefined behavour.
In your case you got the same result by chance. The code is incorrect and may as well print anything.
char *a
a is a pointer to something. That something is a char
int *b
b is a pointer to something. That something is an int
Both a and b are pointers, they only store memory addresses to other things, which is why it is possible (but definitely not reccommended; warning by default, error with -wError) to store the address of an int in a char *.
Dereferencing it is undefined behaviour and "anything could happen" which is why the warning/error is there in the first place.
It may work with your current machine and compiler. It isn't guaranteed to though, and literally anything could break it. Don't do it
In your case it will give the same value because sizeof(int)>size(char). If you really want to see the difference between char* and int*. Lets do this:
Assume: char is of 1 byte, int is 4 byte and addresses are also of 4 byte. To observe the difference between char* and int*.
int k=1024;
char* charptr= &k;
int* intptr=&k;
printf("%02x \n\n", *charptr); // this will simply print `00`
printf("%02x \n\n", *intptr); // this will simply print `400`
int i=0;
for(; i<4 ; i++)
printf("%02x ", *charptr++); // this will print `00 04 00 00`
NOTE: It is a little endian machine. First print displays the content of first byte only therefore we see 00 as output. Third print statements clears everything.
Hope this will help to understand the difference here.
What is the difference between a char pointer and an int pointer ?
Without considering what your code, the answer is simple Char pointer points to a memory address which holds a char value and an int pointer points to one with int value. This is and remains the difference between them. However, when you force the compiler to do something what they haven't been specified to, you either get an error or an unspecified behavior.
So, what's up with your code ?
That has already been explained well in answers but the basic thing is that char is stored as an ascii value and thus in your case an int pointer could point to a char.

C Programming Simple Pointers

I'm a beginner at learning pointers. Here is my code. (Note: I'm still trying to get my head around pointers so my code won't be clean.)
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]){
int a = 1;
char b = 's';
double c = 3.14;
int *ptra;
int *ptrb;
int *ptrc;
ptra = &a;
ptrb = &b;
ptrc = &c;
printf("I initialised int as %d and char as %c and double as %.2f\n", a, b, c);
printf("The address of A is %p and the contents of A is %d\n", ptra, *ptra);
printf("The address of B is %p and the contents of B is %c\n", ptrb, *ptrb);
printf("The address of C is %p and the contents of C is %.2f\n", ptrc, *ptrc);
I expected the following output:
I initialised int as 1 and char as s and double as 3.14
The address of A is 0xbf933094 and the contents of A is 1
The address of B is 0xbf933093 and the contents of B is s
The address of C is 0xbf933098 and the contents of C is 3.14
But instead I get this:
I initialised int as 1 and char as s and double as 3.14
The address of A is 0xbf933094 and the contents of A is 1
The address of B is 0xbf933093 and the contents of B is s
The address of C is 0xbf933098 and the contents of C is 427698.00000
Can someone help for the large number I got when printing the contents of C? Why don't I get 3.14? (The number is actually longer than that but it didn't fit into this textbox. :-))
You are declaring ptra, ptrb and ptrc as pointers to ints. But the type of a pointer is based on what it points to, so it really should be:
int *ptra;
char *ptrb;
double *ptrc;
In your specific case, your program is trying to interpret a double value through an int pointer. Since the sizes of these data types differ on your machine, some of the bits of the double get discarded and you end up with the strange number you're seeing.
This may not always happen the same way - the result of accessing something through the wrong type of pointer is not defined by the C language, but it still might compile. C programmers refer to this as undefined behaviour (a phrase you should really come to terms with if you want to learn C!).
There is also the fact that when you call printf, you need to give it variables of the type it expects from the format string. So if you give it a format string where the first placeholder is %.f, you must give it a first argument that's a double. If you don't, printf will also exhibit undefined behaviour and could do anything (the undefined behaviour may be strange output, crashing, or simply putting out the number you expect... until the worst possible moment).
Your pointers are all of type int. That is not correct. Replace those by
int *ptra;
char *ptrb;
double *ptrc;
Because your pointers are all int*. If you want it to dereference to a double, you need it to be double*. Your compiler should have warned you about incompatible pointer assignment.
You should declare pointers using the corresponding type.
int *ptra;
char *ptrb;
double *ptrc;
you need to change your pointer type to match your data type so the size will be set accordingly.
char *ptrb;
double *ptrc;
If I can just say a few words about typed pointers.
Pointers with a type (as opposed to void* pointers) know how many bytes to advance in memory. For example on 32 bit systems and integer pointer would typically advance four bytes in memory when iterating through an array containing integer values.
A char pointer (guaranteed by the C standard to be always 1 byte) would naturally advance 1 byte at a time.
Let me illustrate this with a small code snippet:
#include <stdio.h>
int main()
{
char array [] = "This is a char array.";
int* int_ptr;
char* char_ptr;
char_ptr = array; /* This is okay, we have a char array and we assign its address to a char pointer */
int_ptr = array; /* It will complain but let's go along with it */
printf("%p, %p, %p\n", array, char_ptr, int_ptr); /* They should all point to the same address in memory */
printf("%p\n", ++char_ptr); /* it will have advanced by one byte */
printf("%p\n", ++int_ptr); /* it will have advance by four bytes */
return 0;
}
I have the following output on my machine:
$ ./a.out
0xbf8b85d2, 0xbf8b85d2, 0xbf8b85d2
0xbf8b85d3
0xbf8b85d6
As you can see they have indeed advanced as we predicted. It is fairly obvious this can cause all sorts of problems when we start dereferencing our pointers and they don't match the underlying type.
Regarding void* pointers, arithmetic on them is illegal.
here the pointer ptrc is referring to the addressof varaible whose data type is integer but you are using it for double.

Storing the address of a string in an array of strings

I'm having some issues with storing an address of a specific value in an array of strings to a pointer and printing it out. Please excuse the bad variable names, they are just for the example.
char **code; // code is an array of 100 strings of length 8 characters
code = malloc (100*sizeof(*code));
for (i=0; i<100; i++) {
code[i]=malloc(8*sizeof(**code));
}
char **r; // r is an array of 16 strings of 32 characters
r = malloc (16*sizeof(*r));
for (i = 0; i < 16; i++)
r[i] = malloc(32*sizeof(**r));
char *a; // a is a pointer to a string
a = (char *) &r[13]; // point a to value at r[13]
*a = (char *)&code[100]; // trying to assign the value of r[13] to the address of code[100]
printf("Code 100 Add: %p a Val: %i\n", &code[100], *sp); // trying to check values.
I'm trying to assign the value of a (which points to r[13], so assign value of r[13]) to the value of the Address of the string at code[100]. Is even a string of 32 characters the best way to do this?
Appreciate any help,
Gareth
a = (char *) &r[13]; // point a to value at r[13]
Turn on your compiler warnings, and pay attention to what the compiler tell you when you remove this cast. You shouldn't need any casts in this code.
The type of r is char** and so the type of r[13] is char*, and the type of &r[13] is char**, which you're assigning to a char*.
P.s., next time please also include the actual error you receive vs what you expected.
To assign a string, use strncpy. Don't copy the pointer value directly because you will free it twice later this way (among other problems).
&r[13] is not a pointer to char.
You just need to
r[13] = code[100]
I do agree with Frederik that you should be careful when free()-ing the allocated memory since you now have two pointers pointing at the same memory block. If you prefer to follows his advice, try the following:
strncpy(r[13], code[100], 8)
Rather than assigning a pointer to a memory address, you're going to want to copy the data at that memory address using strcpy.
With definition of char *a; the *a on the left-hand side of an assignment becomes an lvalue of type char. You can assign pointer values there as integers, as in square peg into a round hole, though it does not make much sense. To copy strings use str[nl]cpy(3).
I hate to ask a question during someone else's question... but shouldn't the char array setup/malloc calls be something more like this? Isn't he allocating too much with sizeof(**code)? And then... if it's for 8 characters... won't we want 9 to make room for '\0'?
char **code; // code is an array of 100 strings of length 8 characters
code = (char**) malloc (100*sizeof(char*));
for (i=0; i<100; i++) {
code[i] = (char*)malloc(9*sizeof(char));
}

Why does my homespun sizeof operator need a char* cast?

Below is the program to find the size of a structure without using sizeof operator:
struct MyStruct
{
int i;
int j;
};
int main()
{
struct MyStruct *p=0;
int size = ((char*)(p+1))-((char*)p);
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
return 0;
}
Why is typecasting to char * required?
If I don't use the char* pointer, the output is 1 - why?
Because pointer arithmetic works in units of the type pointed to. For example:
int* p_num = malloc(10 * sizeof(int));
int* p_num2 = p_num + 5;
Here, p_num2 does not point five bytes beyond p_num, it points five integers beyond p_num. If on your machine an integer is four bytes wide, the address stored in p_num2 will be twenty bytes beyond that stored in p_num. The reason for this is mainly so that pointers can be indexed like arrays. p_num[5] is exactly equivalent to *(p_num + 5), so it wouldn't make sense for pointer arithmetic to always work in bytes, otherwise p_num[5] would give you some data that started in the middle of the second integer, rather than giving you the sixth integer as you would expect.
In order to move a specific number of bytes beyond a pointer, you need to cast the pointer to point to a type that is guaranteed to be exactly 1 byte wide (a char).
Also, you have an error here:
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
You have two format specifiers but only one argument after the format string.
If I don't use the char* pointer, the output is 1 - WHY?
Because operator- obeys the same pointer arithmetic rules that operator+ does. You incremented the sizeof(MyStruct) when you added one to the pointer, but without the cast you are dividing the byte difference by sizeof(MyStruct) in the operator- for pointers.
Why not use the built in sizeof() operator?
Because you want the size of your struct in bytes. And pointer arithmetics implicitly uses type sizes.
int* p;
p + 5; // this is implicitly p + 5 * sizeof(int)
By casting to char* you circumvent this behavior.
Pointer arithmetic is defined in terms of the size of the type of the pointer. This is what allows (for example) the equivalence between pointer arithmetic and array subscripting -- *(ptr+n) is equivalent to ptr[n]. When you subtract two pointers, you get the difference as the number of items they're pointing at. The cast to pointer to char means that it tells you the number of chars between those addresses. Since C makes char and byte essentially equivalent (i.e. a byte is the storage necessary for one char) that's also the number of bytes occupied by the first item.

Resources