Array pointer to find largest number - c

#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a= malloc(sizeof(int)*10);
scanf("%d %d",a,a+1);
if(*a<*(a+1))
{
*a=*(a+1);
}
printf("%d",*a);
return 0;
}
Can I use the same array pointer to input 2 numbers and find largest number among them, as shown in the above code?

Yes, it will work, although it might be perceived as more readable to use bracket notation for array elements. You also only need to malloc space for 2 elements.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = malloc(sizeof(int) * 2);
scanf("%d %d", &a[0], &a[1]);
if(a[0] < a[1])
{
a[0] = a[1];
}
printf("%d", a[0]);
return 0;
}
Read more about pointers and how they work

Yes, you can. Because when you say *a you are pointing to the 0th location of the array and getting the value there and when you say *(a+1) you are pointing to 1st location of the array. Same analogy for &a and &(a+1).

Related

Why Array of Pointer and Array giving same output

1)
How to access array element with array of pointers?
By pointer to an array we can access like this (∗a)[0]
,(∗a)[22]
,….. like this
right?
but how with array of pointer?
2)
Check these three codes , one of them use array and one of them use array of pointer, and 3rd one using double pointer, but all giving same output. Why??
#include <stdio.h>
int ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int *ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int **ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
In *(ptr+5):
ptr is the name of an array.
When an array is used in an expression and is not the operand of sizeof or unary & and is not a string literal used to initialize an array, it is converted to a pointer to its first element. So ptr points to element 0 of the array.
ptr+5 adds five, resulting in a pointer to element 5 of the array.
* dereferences the pointer, producing the contents of element 5 of the array.
Since the array is defined outside any function, it is initialized to zero. Therefore element 5 is zero, so *(ptr+5) is zero. Similarly, *(ptr+3) is zero, so comparing them shows they are equal.
The examples with int ptr[12];, int *ptr[12];, and int **ptr[12]; just change the types of the elements in the array. In each case *(ptr+5) and *(ptr+3) refer to elements 5 and 3 of the array. In each case, the values of the elements are zero (null pointers for the pointer types).
If you want to see differences between different elements of the array, then assign different values to the elements of the array.
Just keep incrementing the pointer as you go along reading the array. Analyze the
code below:
#include <stdio.h>
int main(void) {
int *ptr[3];
int a[] = { 0,1,2};
int b[] = { 3,4,5 };
int c[] = { 6,7,8 };
ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
for (int i = 0;i < 3;i++)
printf("%d %d %d\n",*ptr[0]++,*ptr[1]++,*ptr[2]++);
return 0;
}
Answered in comments.

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.

Structure arrays with pointer

I'm learning C.I wrote code and error is "passing argument 1 of 'strcpy' makes pointer from integer without a cast".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct humans{
sname[20];
}human;
int main(){
human *person=(human *)malloc(sizeof(human)*1);
int i,k,z;
for(i=0;i<5;i++){
person=(human *)realloc(person,sizeof(human)*(i+1));
strcpy(*person[i].sname , "john");
}
for(i=0;i<5;i++){
printf("%s",*person[i].sname);
}
return 0;
}
I want to use malloc/realloc.
Where you have *person[i].sname, you want person[i].sname instead. When you put * before it, you force the array to decay to a pointer to its first element which, when dereferenced, gives you the value of the first element.
Also:
person=(human *)realloc(person,sizeof(human)*1);
This 1 should be i + 1.
I fixed the direct issues in your program.
The deeper point here though is how to get to the pointer you want.
array[4] gets the value of the 4th element.
array gets the pointer to the first element
&array[4] gets the pointer to the 4th element
array + 4 gets the pointer to the 4th element
*(array + 4) gets the value of the 4th element
*array[4] gets the value, treats it as a pointer and tries to get a value from the pointers target - this would require extra fiddling to convince the compiler what type that would be. In most cases this is likely meaningless.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct humans {
char sname[20];
}human;
void MyStrCpy(char * dst, int dst_n, char * src, int src_n)
{
for (int n = 0; n < dst_n && n < src_n; ++n)
{
dst[n] = src[n];
if (src[n] == 0) break;
}
dst[dst_n] = 0;
}
int main() {
human *person = (human *)malloc(sizeof(human) * 1);
int i, k, z;
for (i = 0; i<5; i++) {
person = (human *)realloc(person, sizeof(human)*(i + 1));
//I replace strcpy so it compiles on my machine
MyStrCpy(person[i].sname, 20, "john", 5);
person[i].sname[20] = 0;
}
for (i = 0; i<5; i++) {
printf("%s\n", person[i].sname);
}
return 0;
}

Why won't changing this value work?

So I'm trying to change the value at x[2] from 0 to 8 using a method, the way I have this isn't working. How can I do this? I tried searching around but came to no avail.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changevar(int* x){
int* y;
y = &x[2];
y = 8;
}
int main(int argc, char** argv){
int* c;
c = (int*) malloc(sizeof(int));
printf("here %d\n", c[2]);
changevar(&c);
printf("here %d\n", c[2]);
free(c);
}
EDIT: I'm new to pointers
You first need to allocate enough space:
c = malloc(3 * sizeof(int));
Notice that I didn't cast the return value.
The values are not initialized to zero. They can be anything ("undefined"). You can clear it with:
memset(c, 0, 3 * sizeof(int));
Next, you'll need to pass this value as is to your function. (It's already a pointer, after all.)
changevar(c);
Within your function, you'll need to dereference the address to access it:
*y = 8;
Those are the errors I see.
So there are two issues that are standing out to me.
You're only allocating memory for one int in your malloc call but trying to access memory that would suggest you allocated a minimum space for 3 ints.
Your function's parameter is supposed to be a int*, however with changevar(&c) you're passing in a int** because you giving the address of a pointer.
To fix these only a couple of changes need to be made...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changevar(int* x){
x[2] = 8; // <-- can be simplified to this one line
}
int main(int argc, char** argv){
int* c;
int amt = 3; // <-- number of ints you want to be able to have space for
c = malloc(sizeof(int) * amt); // <-- multiply the size and the amount you want
printf("here %d\n", c[2]);
changevar(c); // <-- remove the '&' from the argument to just pass the pointer 'c'
printf("here %d\n", c[2]);
free(c);
}
The output becomes:
here 0
here 8
Garbage values are being printed because size of array c is 1.
c = (int*) malloc(sizeof(int));
will create an array c of size 1.
c[2] is a garbage value. (In most systems, 0 is printed instead of a garbage number.)
Your &c[2] and y do not refer to the same address.
What you want to do is probably this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changevar(int** x){
*(*x+2)=8;
}
int main(int argc, char** argv){
int* c;
c = (int*) malloc(3*sizeof(int));
for(int i=0;i<3;i++){
c[i]=0;
}
printf("here %d\n", c[2]);
changevar(&c);
printf("\nhere %d\n", c[2]);
free(c);
}
Prints:
here 0
here 8

Manipulate variable length two dimensional array through a function

I am trying to write data into a variable length two dimensional array and my program keeps seg-faulting when I call myfunc but it works fine when I try to perform the same manipulation outside of a function. I can tell that the issues is that the address pointed to at array[0] doesn't equal the address pointed to at data[0]. Can someone advise me as to the root cause of this issue and proper way to rewrite myfun.
void myfun(unsigned char **array){
printf("array = %p, array[0] = %p\n", array, array[0]);
//This line below causes a segfault
strcpy(array[0], "Position0");
}
int main(void) {
int row = rand() % 5 + 1; // random number between 1-5
int col = rand() % 10 + 20; // random number between 20-29
unsigned char data[row][col];
printf("data = %p, data[0] = %p\n", data, data[0]);
//This function call causes a segfault
myfun(data);
printf("%s\n", data[0]);
//This works
strcpy(data[1], "Position1");
printf("%s\n", data[1]);
return 0;
}
Since you are clearly using C99 or later and a compiler with VLA (variable length array) support, you can write the function correctly quite easily:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void myfun(int rows, int cols, char array[rows][cols])
{
printf("array = %p, array[0] = %p\n", array, array[0]);
strcpy(array[0], "Position0");
printf("a[0] = [%s]\n", array[0]);
}
int main(void)
{
int row = rand() % 5 + 1; // random number between 1-5
int col = rand() % 10 + 20; // random number between 20-29
unsigned char data[row][col];
printf("data = %p, data[0] = %p\n", data, data[0]);
myfun(row, col, data);
printf("%s\n", data[0]);
strcpy(data[1], "Position1");
printf("%s\n", data[1]);
return 0;
}
The problem is the function definition. If you want to pass a matrix the way you did, you have to allocate it dynamically, but that's another story. I'll explain the error.
The C language actually implement the static matrices as a single array of size row*col. That is for efficiency.
When you pass the static matrix to that function, you got a problem: it expects a double pointer, but what you pass is actually a single pointer requiring the number of columns. You have to write like this:
void myfun(unsigned char array[][col]){ ...
That's how you should define it, where col is the number of columns.
The problem's that you don't know the number of columns, it's variable, so I suggest you use malloc or calloc to alocate a dynamic matrix.
Editing: look at this link posted as comment by n.m. for details on the static matrix that C implements: Is 2d array a double pointer?

Resources