Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 06:29 26 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : csub and array - help please

     Page 1 of 2    
Author Message
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 351
Posted: 07:44pm 06 Mar 2024
Copy link to clipboard 
Print this post

Can someone explain to me with a simple example how I pass an array from mmbasic to a csub? increase the values in it by one and get another one back if necessary?


dim t% = (1,2,3,4)
dim t2%(3)
ctest t%(),t2%()

csub ctest
 ...
end csub


What does the C part look like for compiling ... ?


#include <stddef.h>

void ctest(long long int *t[], long long int *t2[]) {     ??? call ok? ??

and here how?

}

 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4037
Posted: 07:54pm 06 Mar 2024
Copy link to clipboard 
Print this post

I'm guessing, because it's been a while since I looked at CSUBs and I can't recall whether I did arrays:

#include <stdint.h>

void ctest(int64_t len, int64_t* t1, int64_t* t2) {
 for (int i = 0; i < len; ++i) {
   t2[i] = t1[i] + 1;
 }
}


And call with:

ctest 4, t%(), t2%()


Note how you need to pass in the length of the array, C doesn't know how long a normal array passed as an argument is.

Good luck,

Tom
Edited 2024-03-07 05:54 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 351
Posted: 08:43pm 06 Mar 2024
Copy link to clipboard 
Print this post

  thwill said  
Good luck,

Tom


Error: Invalid address - resetting

No luck :-(


Matthias
Edited 2024-03-07 06:44 by homa
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4037
Posted: 08:58pm 06 Mar 2024
Copy link to clipboard 
Print this post

Try this:

#include <stdint.h>

void ctest(int64_t* len, int64_t t1[], int64_t t2[]) {
  for (int i = 0; i < *len; ++i) { ' <-- Note *len
    t2[i] = t1[i] + 1;
  }
}


Best wishes,

Tom
Edited 2024-03-07 06:58 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 351
Posted: 09:14pm 06 Mar 2024
Copy link to clipboard 
Print this post

does! thx

but what exactly is the * for ? i'm still at the very beginning with c


#include <stdint.h>

void ctest(int64_t* len, int64_t t1[], int64_t t2[]) { ' <-- and why here and not *len ?
 for (int i = 0; i < *len; ++i) { ' <-- Note *len
   t2[i] = t1[i] + 1;
 }
}



and why doesn't this work (yes, the variable names don't fit, but just as an example)?
size_t n = sizeof(a) / sizeof(a[0]);


Matthias
Edited 2024-03-07 07:27 by homa
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 479
Posted: 10:13pm 06 Mar 2024
Copy link to clipboard 
Print this post

The * means you are passing a pointer to a memory region, instead of a value. For arrays your are passing the start address in memory of the array.
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1241
Posted: 10:30pm 06 Mar 2024
Copy link to clipboard 
Print this post

  LeoNicolas said  The * means you are passing a pointer to a memory region, instead of a value. For arrays your are passing the start address in memory of the array.

and applied to a pointer this means a dereference. I.e. the contents of the memory at the location referenced by the pointer.

But Matthias does it very well! Congratulations!

Michael


I put together the above code again.
Dim t%(3) = (1,2,3,4)
Dim t2%(3),l%,i%

l% = Bound(t2%())
ctest l%, t%(), t2%()
For i%=0 To l%
 Print i%,t%(i%),t2%(i%)
Next

End

'File arrayinc1.bas written 06-03-2024 23:15:29 v1.44
CSub ctest
 00000000
 B087B5F0 60F8AF00 607A60B9 617B2300 697BE012 68BA00DB 681A18D3 6979685B
 687800C9 20011846 18122100 6032414B 697B6073 617B3301 001C697B 001D17DB
 681A68FB 429D685B D1E2DC02 D9E04294 46BD46C0 BDF0B007
End CSub


#include <stdint.h>
#include "PicoCFunctions.h"

void ctest(int64_t* len, int64_t t1[], int64_t t2[]) {
 for (int i = 0; i <= *len; ++i) {
   t2[i] = t1[i]+1;
 }
}

causality ≠ correlation ≠ coincidence
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3801
Posted: 10:32pm 06 Mar 2024
Copy link to clipboard 
Print this post

Then when you use the pointer (i < *len) it means to use the value it (*len) points to.

John
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1109
Posted: 12:04am 07 Mar 2024
Copy link to clipboard 
Print this post

MATH ADD in(), 1 ,out()

Of course, that won't learn ya nuttin about CSUBs.
Visit Vegipete's *Mite Library for cool programs.
 
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 351
Posted: 12:16pm 07 Mar 2024
Copy link to clipboard 
Print this post

Thank you all,

Michael: bound in basic is a good solution.

Thanks for explaining the * as a pointer to the address.
But my question why the * in the function name is "int64_t* len" on the left and then "*len" is still not answered.

And why does the array not need a *=pointer? Is that per se always the start address through the square brackets []?

Why a sizeof does not work is also only partly self-explanatory. In C itself, the program also knows when a function is called with an array, doesn't it?

Phew, C is different.

Matthias
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6786
Posted: 12:26pm 07 Mar 2024
Copy link to clipboard 
Print this post

C is closely related to an antiquarian minor dialect of Njerep, I think. It may as well be to me. :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4037
Posted: 12:43pm 07 Mar 2024
Copy link to clipboard 
Print this post

  homa said  But my question why the * in the function name is "int64_t* len" on the left and then "*len" is still not answered.


In this function prototype:

void ctest(int64_t* len, int64_t t1[], int64_t t2[]);


int64_t* len

Says that `len` is a pointer to (i.e. the address of) an int64_t containing the length.

Within the function:
- The value of `len` is the memory address.
- The value of `*len` is the contents of that memory address, you are de-referencing the pointer.

Note that MMBasic doesn't simply pass the value of `len` because MMBasic passes arguments to ALL (not just CSUB) subroutines and functions by reference not by value.

  homa said  And why does the array not need a *=pointer? Is that per se always the start address through the square brackets []?


This function prototype:

void ctest(int64_t* len, int64_t* t1, int64_t* t2);


Means exactly the same thing to the compiler as the first one, and is infact the canonical form with the former just being prettier. When you pass an array to a function you always pass a pointer to the first (0'th) element of that array.

MMBasic does not pass the address of the array, it passes the address of the first element of the array which is why you don't need ** or a * and a [].

Why a sizeof does not work is also only partly self-explanatory. In C itself, the program also knows when a function is called with an array, doesn't it?


sizeof() is evaluated at compile time (excluding C99 variable length arrays which are out of scope) and thus can't be used to determine the size of an array passed to a function.

sizeof(t), sizeof(t1), sizeof(t2) will all be identical = 4 because they are 32-bit pointers.

Note however with a local or global variable (not parameter) in a function you can do:

void foo() {
  int64_t a[10];
  printf("%d\n", sizeof(a) / sizeof(a[0]));
}


And this (assuming I haven't cocked up) will print 10 because the sizeof(a) is 80 bytes and the size of one element is 8 bytes.

  homa said  Phew, C is different.


So is Spanish ;-)

Best wishes,

Tom
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1241
Posted: 12:56pm 07 Mar 2024
Copy link to clipboard 
Print this post

Very well explained, Tom!  

  thwill said  ... sizeof(t), sizeof(t1), sizeof(t2) will all be identical = 4 because they are 32-bit pointers. ...

ähmm ... not 64-bit pointers?  

Best regards
Michael
causality ≠ correlation ≠ coincidence
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9115
Posted: 01:08pm 07 Mar 2024
Copy link to clipboard 
Print this post

Matthias

You are asking questions about basic C syntax so the full answer is Kernighan and Ritchie "The C programming language" which is available online free if you look.

C is very easy and maps pretty much 1:1 onto MMBasic EXCEPT for pointers and pointers are what makes C so powerful

I'll try and answer your questions but you will find you need to go deeper than we can answer in a forum thread.

sizeof can only work on declared data
so
int b[10];
int c=sizeof(b);
works

but MMbasic does not declare arrays in that way. It creates them on a pre-allocated area of memory called the MMBasic Heap. Therefore sizeof cannot know their size

When you enter a CSub passing a Basic variable "BVar" then the CSub gets a pointer to the memory holding that variable; let's call that pointer Cvar

*Cvar says "the data item that is pointed to by Cvar"

So in Tom's code *len is the actual value passed by MMBasic whereas just "len" is the pointer to that data item.

Now lets look at arrays. When you pass an array to a CSub what the CSub sees is a pointer to the first element of the array so:

*Cvar is exactly the same as Cvar[0] in both cases a pointer to the first element of the array.

How then do we get the second element of the array? Cvar[1] obviously. But what this is doing is effectively adding the size of a single element (8 bytes in our case) to Cvar and using this new pointer to get the data
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4037
Posted: 01:13pm 07 Mar 2024
Copy link to clipboard 
Print this post

  twofingers said  Very well explained, Tom!  


Thanks.

  twofingers said  ähmm ... not 64-bit pointers?  


I don't get your point, `len`, `t1` and `t2` are I believe, at least on the Pico, 32-bit pointers to 64-bit integers.

Without running it myself, the output from:

printf("%d,%d\n", sizeof(len), sizeof(*len));
printf("%d,%d\n", sizeof(t1), sizeof(*t1));
printf("%d,%d\n", sizeof(t2), sizeof(*t1));


Should be:

4,8
4,8
4,8


Best wishes,

Tom
Edited 2024-03-07 23:19 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1241
Posted: 01:23pm 07 Mar 2024
Copy link to clipboard 
Print this post

  thwill said  
  twofingers said  ähmm ... not 64-bit pointers?  


I don't get your point, `len`, `t1` and `t2` are on the Pico I believe 32-bit pointers to 64-bit integers.

Tom: sorry, my mistake! I was confused.

Michael
causality ≠ correlation ≠ coincidence
 
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 351
Posted: 03:55pm 07 Mar 2024
Copy link to clipboard 
Print this post

Hi Tom and Peter,
Thanks a lot for helping me out here!


Dude, I still have this on my shelf and in German, but it's still Spanish to me, I have a bad translation ;-)
No kidding, a later edition must be much better in translation. I'll see if I can still find it. Reading English is okay, but really learning it is a challenge for me as an old man.



@Tom
I was confused about the *-pointer because I read it here, directly to the right of the variable name and not to the left of the type: https://www.thebackshed.com/forum/ViewTopic.php?TID=12289&PID=149258#149258

void waitabit(long long int *w){
uSec(*w);
}


Thanks again and I will now try it with the Raycaster, the weekend can come ...

Matthias
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3801
Posted: 04:08pm 07 Mar 2024
Copy link to clipboard 
Print this post

  homa said  I was confused about the *-pointer because I read it here, directly to the right of the variable name and not to the left of the type: https://www.thebackshed.com/forum/ViewTopic.php?TID=12289&PID=149258#149258

void waitabit(long long int *w){
uSec(*w);
}


That looks like you have left & right swapped.

When starting out, it's probably best to stick to as few pointers as you can, and especially to as few levels of indirection (it's possible to have pointers to pointers etc, which can confuse).

C's quite a compact yet powerful language.  MMBasic is quite a big, complex thing and it uses lots of C's features.  Some of the C syntax takes some getting used to.

In other words, for a C beginner trying to get used to MMBasic's internals, you have quite a cliff to climb.

John
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4037
Posted: 04:12pm 07 Mar 2024
Copy link to clipboard 
Print this post

  homa said  
void waitabit(long long int *w){
uSec(*w);
}


OK, so the whitespace around the * is I'm pretty sure always irrelevant, for a pointer I usually put it with the type so I would have written:

void waitabit(long long int* w){
  uSec(*w);
}


Except I wouldn't have written `long long int` because at least when I learnt C that could be anything for 32-128 bits long. In this case I would use int64_t which is guaranteed (?) to be a 64 bit integer, so:

void waitabit(int64_t* w){
  uSec(*w);
}


And in this case `w` is a 32-bit pointer to the time you want to "wait" and `*w` is the 64-bit time you want to wait.

Best wishes,

Tom
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9115
Posted: 04:20pm 07 Mar 2024
Copy link to clipboard 
Print this post

  Quote  OK, so the whitespace around the * is I'm pretty sure always irrelevant, for a pointer I usually put it with the type so I would have written:


I'm never sure on this one so I always put it with the variable


int64_t* a,b;
int64_t *a,b;
 
     Page 1 of 2    
Print this page
© JAQ Software 2024