getting EXITED error:pointer to an array in c - c

int main()
{
unsigned char a[3];
unsigned char (*p)[3]=NULL;
unsigned char *q=NULL;
int i = 0;
a[0]=0;
a[1]=1;
a[2]=2;
p=&a;
for(i=0;i<3;i++){
if((*p)[3] == a[3]){
printf("*p[%d]:%d a[%d]:%d",i,(*p)[3],i,a[3]);
}
}
}
o/p:
*p[0]:0 a[0]:0*p[1]:0 a[1]:0*p[2]:0 a[2]:0
Exited: ExitFailure 14
I want to copy an array of size 3 to a pointer and to do a comparision. I have written a sample program. But i'm getting an error value.
I ran this using an online c compiler . (codepad.org)
Please help me in identifying my mistakes.

Your variable p is an array, not a pointer. You can't re-assign an array to point somewhere else, so the line
p = &a;
is not valid.
Also, C indexes from 0 as you seem to know, so comparisons using index [3] for arrays of size 3 are not valid.
Further, in your comparison loop you're not actually using i to index, but instead always comparing using the invalid constant index [3].
It's not very clear from your code (q is not used, for instance), but it sounds as if you want to do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char a[3];
unsigned char *p;
p = malloc(sizeof a);
if(p != NULL) /* If allocation succeeded, p is valid. */
{
int i;
memcpy(p, a, sizeof a);
for(i = 0; i < sizeof a; ++i)
{
if(p[i] == a[i])
printf("p[%d]:%d a[%d]:%d\n", i, p[i], i, a[i]);
}
free(p);
}
Of course, this will always print all the numbers, since memcpy() will never fail to copy the memory. :)

Here You have declared the return type of main function as int, but you are not returning anything from it.
So return any integer value (like 1) or make the main function's return type void.

Related

If I allocate only 4 bytes for single int, how then pointer can store second int?

As I found on one site following code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p1 = malloc(4*sizeof(int)); // allocates enough for an array of 4 int
int *p2 = malloc(sizeof(int[4])); // same, naming the type directly
int *p3 = malloc(4*sizeof *p3); // same, without repeating the type name
if(p1) {
for(int n=0; n<4; ++n) // populate the array
p1[n] = n*n;
for(int n=0; n<4; ++n) // print it back out
printf("p1[%d] == %d\n", n, p1[n]);
}
free(p1);
free(p2);
free(p3);
}
Output:
p1[0] == 0
p1[1] == 1
p1[2] == 4
p1[3] == 9
Now following that code above I did this:
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
int main()
{
int *ip = (int*)malloc(1 * sizeof(int));
ip[0] = 2;
ip[1] = 9;
printf("%d %d",ip[0],ip[1]);
return 0;
}
Output: 2 9
So how then my pointer *ip can store more than one int when I only allocated bytes for single int?
You're writing into memory which is outside of the bounds of the array. Sadly, there is no compiler check for this, but it sometimes works.
Note: This is undefined behavior and should not be used under any circumstances.
Remember, ip[1] is equivalent to *(ip + 1), which is syntactically valid for any pointer, even if ip is pointing to single int and not an array of ints.
Dereferencing or writing to ip[1] is undefined behavior. Try adding free(ip) before the return 0 in your second program and observe the behavior then.

what's *p when p is declared as int (*)[size] and assigned to an array

code:
int arr[5] = {1,2,3,4,5};
int (*p)[5] = &arr;
printf("p:%p\n",p);
printf("*p:%p\n",*p);
result: p = *p = arr = 0x7ffee517c830 they are all the address of the array
The right way to use p to visit arr[i] is *(*p+i)
The type of pointer p is int(*)[5], so p point to an array which type is int [5]. But we can't say that p point to an invisible shell of arr, p is a variable after all. It stores the address of arr, which is also the address of arr[0], the first element of arr.
I thought *p will get me 1, which is the first element of arr.
The dereference operation means take the value in p as address and get the value from this address. Right?
So p stores the address of arr,which is 0x7ffee517c830 here, and 1 is stored in this address. Isn't **p illegal? The first dereference give us 1, and second dereference will use 1 as address which is illegal.
What I am missing?
The result of *p is an lvalue expression of array type. Using (*p) is exactly the same as using arr in any expression you could now think of.
For example:
&*p means &arr
**p means *arr (which is legal).
(*p)[i] means arr[i].
sizeof *p means sizeof arr.
Arrays are not special in this regard. You can see the same phenomenon with int x; int *q = &x;. Now *q and x have exactly the same meaning.
Regarding your last paragraph, I think you are confusing yourself by imagining pointers as glorified integers. Some people teach pointers this way but IMO it is not a good teaching technique because it causes the exact confusing you are now having.
If you dereference an int(*)[5] you get an int[5] and that's all there is to it. The data type matters in dereferencing. It does not make sense to talk about "dereferencing 0x7ffee517c830". Again this is not peculiar to arrays; if you dereference a char ***, you get a char ** etc.
The only way in which arrays are "different" in this discussion is what happens if you try to do arithmetic on them, or output them, etc. If you supply an int[5] as a printf argument for example, there is implicit conversion to int * pointing at the first of those 5 ints. This conversion also happens when applying the * operator to an int[5], which is why you get an int out of that.
p is declared as a 'pointer to int[5]'.
arr is declared as an 'int[5]`
so the initializer p = &arr; is not really that strange. If you substituted any primitive type for int[5] you wouldn't bat an eye.
*p is another handle on arr. so (*p)[0] = 1.
This really only comes up in wierd cases. It's most natural where you dereference the pointer-to-array using the subscript operator. Here's a contrived example where I want to pass a table as argument.
#include <stdio.h>
int print_row_range(int (*tab) [2], int first, int last)
{
int i;
for(i=first; i<= last; i++)
{
printf("{%d, %d}\n", tab[i][0], tab[i][1]);
}
}
int main(int argc, char *argv[])
{
int arr[3][2] = {{1,2},{3,4},{5,6}};
print_row_range(arr,1,2);
}
This example treats the table as an array of rows.
Dereferencing doesn't give you a value. It gives you an object, which can be used as a value of its type if it can be converted to.
*p, being identical to arr, is an object of an array of 5 ints, so if you want to get an integer from the array, you must dereference it again like (*p)[3].
Consider a bigger example:
int arr[5][5];
int (*p)[5] = arr;
Now you get arr[0] with *p, which itself is an array of 5. Here comes the difference:
*( p+1) == arr[1];
*(*p+1) == arr[0][1];
^ ^^^
Got the point?
One use case is to be able to allocate with malloc an 2D (or more) pointer of arrays with only one malloc:
#include <stdio.h>
#include <stdlib.h>
static int (*foo(size_t n))[42] {
return malloc(sizeof *foo(0) * n);
// return malloc(sizeof(int [n][42]); works too
}
int main(void) {
size_t n = 42;
int (*p)[42] = foo(n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}
I think this very funny.
One more with VLA:
#include <stdio.h>
#include <stdlib.h>
static void *foo(size_t elem, size_t n, size_t m) {
return malloc(elem * n * m);
}
int main(void) {
size_t n = 42;
int (*p)[n] = foo(sizeof **p, n, n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}

What does happen when we equation two pointer in C?

This is a C code to sort the substrings of a large string starting from each index but I cannot understand how can we sort the array a in the code.
As far as I understand:
we refer a[i] to &c[i] and thus it created n arrays but doesn't
&a[i][1] == &a[i+1][0]?
Since a[i] = &c[i], is it true that &a[i][0] == &c[i]?
If not, this looks like a faster way to create n(length of original
string) arrays, without actually copying it. Is that true?
My code
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define M 1
#define MAXN 5000000
char c[MAXN], *a[MAXN];
int pstrcmp(char **p, char **q){
return strcmp(*p, *q);
}
int main(){
int i, ch, n = 0, maxi, maxlen = -1;
while ((ch = getchar()) != EOF) {
a[n] = &c[n];
c[n++] = ch;
}
c[n] = 0;
qsort(a, n, sizeof(char *), pstrcmp);
printf("%s",a[1]);
return 0;
}
I'm guessing pstrcmp is a wrapper around strcmp that compares two pointers to char pointers. Something like:
int pstrcmp(const void *a, const void *b) {
return strcmp(*(char**)a, *(char**)b);
}
To answer your questions,
Yes, &a[i][1] == &a[i+1][0]. They both point to the i + 1-st character of c.
Yes, &a[i][0] == &c[i].
You are indeed creating pointers to n strings, but there is a catch: if you altered any string (say, the last character), you would be altering more strings. So these strings are not independent.
Conceptually, a[i] is a pointer to the suffix of c starting at position i. The program then sorts a according to the values of the strings they point to. So, for c = "abacaba", you would get { "a", "aba", "abacaba", "acaba", "ba", "bacaba", "caba" }.
Please note that there are faster ways to build suffix arrays.
In this code, I don't see sub-strings, as you don't build any.
Technically, a is an array of pointers of type char that could make it an array of strings, but the way you link c to a, effectively a is an index of c.
Inside the loop, you fill the index char by char. Later when you sort a, you sort the index.
The problem with the index is, that you can't really print it out as a string, as it is not a char * that the %s printf format modifier expects, but a char **. This alone should warn you about something spooky. I see that you evaded this problem as hard coding a[1] as parameter, but the sole problem of what index to use, tells, that you are going in the wrong way.
I've slightly edited your code, how it would print out the sorted array. If you think it is not doing what you want, there is a misunderstanding between what you want and what your code does (except the last printf).
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAXN 5000000
// This is an array of characters:
char c[MAXN];
// This is an array of pointers pointing to individual characters. Essentially, this is an index.
char *a[MAXN];
static int pstrcmp(const void *p1, const void *p2){
// wrapper between strcmp and qsort's compare signature.
// See: man 3 qsort -- http://linux.die.net/man/3/qsort
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
int main() {
int ch;
size_t n = 0;
while ((ch = getchar()) != EOF) {
// In this loop, you systematically build up an index, where a[i] points to c[i].
a[n] = &c[n];
c[n] = ch;
n++;
}
c[n] = 0;
qsort(a, n, sizeof(char *), pstrcmp); // Now, you sort the _index_.
printf("\nc: %s\n", c); // Print Original array.
printf("a: "); // Print Ordered array:
for (size_t i = 0; i < n; i++)
printf("%c", *a[i]); // Look at the indirection
printf("\n");
return 0;
}

Why Does This Kind of Pointer Arithmetic Work In A Function, But Not In Main?

Here is my code that works. The function initializes the array, a, to values 0 - 3
int main(void)
{
int a[4];
pointer(a);
return 0;
}
void pointer(int* a)
{
int *p, i;
p = a;
for(i = 0; i < 4; i++)
{
*a++ = i;
printf(" %d", p[i]);
}
}
But when I combine it all into main(), it no longer works.
int main(void)
{
int a[4], *p, i;
p = a;
for(i = 0; i < 4; i++)
{
*a++ = i;
printf("%d", p[i]);
}
return 0;
}
Instead, it prints out memory addresses or something. It works when I dynamically allocate a[], so I'm guessing it has something to do with the way a[] is managed in memory. Can someone tell me why the second main() doesn't work?
In the function pointer, the argument a is a pointer. But in main, a is an array, you can't modify an array name, so *a++ = i is invalid.
I can't even compile your code, and the error illustrates why:
$ gcc -o foo foo.c
./foo.c:9:11: error: cannot increment value of type 'int [4]'
*a++ = i;
~^
1 error generated.
You aren't actually using a pointer in your code at all. If you change it as follows, it works as you expect:
#include <stdio.h>
int main(void)
{
int a[4], i;
int* p = a;
for(i = 0; i < 4; i++)
{
*p++ = i;
printf("%d", a[i]);
}
return 0;
}
C arrays decay into pointers in some circunstances, but they aren't pointers. Use p instead of a.
It works when you dynamically allocate a because malloc() returns a pointer, not an array.
you should know the differences between array and pointer.I suggest .
In function,the array you put in will turn to pointer(point to first element of array),it's a variable of pointer,so you can do increasement,in main,a is a address of first element,it's constant,so you can't change.you should change pointer p.
In functions you'r passing the array address point to a pointer. and pointer is accessing each variable when u increment it. this is called a walking pointer.
but in case when u use it in main you'r assuming that array is a simple . Think of an array declared by compiler like
int *const array;
so when you try to increment it. it pops an error. so use one more Walking pointer inside
main so u traverse the array

Problems writing the memset function

I am writing the memset function and my code is below, I am having a problem
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
I also tried pChar[i] = the value we want and still not working. It gives me some trash numbers that do not make any sense.
And I am calling it:
memsetFun(address, num, size);
printf("value at %p is %d\n", address, *((int*) address));
Where I call the address (I just input the address)
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4
Your code looks fine to me and several people here have commented that it works on their system.
So the obvious thing to do is to debug it - that's a skill that will come in handy quite a bit in future :-) You should learn it now.
What does the following code output when you run it?
void* memsetFun(void* pointer, int c, int size) {
printf("A %x %d %d\n", pointer, c, size);
if ( pointer != NULL && size > 0 ) {
printf("B\n");
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
printf("C %d (%d)", i, *pChar);
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
printf(" -> (%d)", i, *(pChar-1));
}
}
printf("D\n");
return pointer;
}
From the output, it should be clear what paths the code is taking and what your parameters are (which will greatly assist the debugging process).
Update:
If you're filling your memory block with anything other than zeros and using this:
printf("value at %p is %d\n", address, *((int*) address));
to print it out, you will get strange results.
You're basically asking for a number of those bytes to be interpreted as an integer. So, for example, if you filled it with 0x02 bytes and you have a 4-byte integer type, you will get the integer 0x02020202 (33686018), not 0x02 as you may expect. If you want to see what the first character value is, use:
printf("value at %p is %d\n", address, *((char*) address));
And based on your latest question update:
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4
If that's a single character and you're printing it as a character, there's probably nothing wrong at all. Many output streams will give you that for a control character (CTRL-D in this case, ASCII code 4). If you instead filled it with ASCII code 0x30 (48), you would see the character '0' or ASCII 0x41 (65) would give you 'A'.
As pointed out already, your function works as it should. Here is a complete example:
#include <assert.h>
#include <string.h>
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
int main() {
// Your memset
char a[10];
memsetFun(a, 'A', sizeof(a));
// Uses system memset for verification
char b[10];
memset(b, 'A', sizeof(b));
assert(sizeof(a) == sizeof(b));
assert(memcmp(a, b, sizeof(b)) == 0);
return 0;
}
return p; prevents this from compiling: p is not defined.
A minor efficiency issue—in practice it would have little effect, since any good compiler would rearrange it, but coding perfectionists wouldn't allow it to remain—the assignment to temp is inside the loop, but it is the same assignment every time. That is, the assignment to temp can be moved before the loop.
You return p, which isn't defined/doesn't point to anything in particular. Maybe you meant pointer?
The code is logically correct. With the p => pointer change it works correctly.
Clarify how exactly it is "not working". Perhaps you are not understanding what it is supposed to do?
You are probably getting trash numbers because you are casting from an int (4 bytes) to an unsigned char (1 byte), so if c > 255 or < 0 you won't be memsetting the values you are expecting to be.
I ran a test if your program setting the memory of an int vector of 5 elements setting with the value 0x01.
The problem here is that you are iterating in a vector of int for example (which is 4 bytes) but iterating over it using char pointer arithmetic (1 byte). If you want to memset 0x01 for example you will write this number per value in the vector: 00000001000000010000000100000001
which gives me the same value using the original memset.
Your function, as is, works for me.
I suppose you're calling it wrong. I call it like this
char a[100];
memsetFun(a, 0, sizeof a);
int b[100];
memsetFun(b, 0, sizeof b);
How are you calling your memsetFun()?
Edit
With
int b[100];
memsetFun(b, 9, sizeof b);
as an int is made up of 4 bytes (on my system) each value will be set to 0x09090909 or 151587081.
That is exactly what it's supposed to do. Your function is working perfectly fine. The value "0x4" is not the ASCII character '4'.

Resources